Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Need suggestions on using the Best Practice/Code Structure for Visual Novel Game
Started by sani3798 Oct 21 2019 02:45 AM

- - - - -
4 replies to this topic
codeoptimization codestructure
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

sani3798

[GLOBAL: userInfoPane.html]
sani3798
  • Observer

  • 4 posts
  • Corona SDK

Hi People, hope everyone is doing great.
 
My team and i are working on a Visual Novel project and we are using Corona SDK to code our entire game. I wanted to seek help and advise from experienced Corona developers on how i could potentially structure my code a bit better that it is well optimized and eat's up less resources. 
 
Kindly observe the following code:
 
 
local tapCount = 0 
 
function TransitionFunc()

    tapCount = tapCount + 1

    if(tapCount == 1then

        --Sarah Dialog Disappear
       transition.to( DialogText,{ alpha = 0, time = 800 } )

        --Dialog Text for Kamali
        DialogText = display.newText" What day is it again?... "245280"SceneAssets/GeoSansLight"14)
        DialogText:setFillColor0,0,0 )
        DialogText.alpha = 0

        --Sarah Dialog Disappear
       transition.to( DialogText,{ alpha = 1 ,time = 800 } )

       ButtonAppearDisappear()

    elseif(tapCount == 2then

       --Kamali Transition Disappear
       transition.to( K1,{ alpha = 0,time = 800 } )


       --Dialog Text Transition Disappear
       transition.to( DialogText,{alpha = 0 ,time = 600} )

       --Sarah Name Image Disappears
        transition.to( Sarah_Name,{alpha = 0 ,time = 800} )

        --Dialog Text for Kamali
        DialogText = display.newText"Tuesday?...."245280"SceneAssets/GeoSansLight"14)
        DialogText:setFillColor0,0,0 )
        DialogText.alpha = 0

        --Kamali Transition Appear
       transition.to( K2,{ alpha = 1,time = 800 } )

        --Kamali Name Image Appears
        transition.to( Kamali_Name,{alpha = 1 ,time = 800} )

        --Dialog Text Appears
        transition.to( DialogText,{ time = 800, alpha = 1})

        ButtonAppearDisappear()
 
--Inside scene:create
button:addEventListener"tap", TransitionFunc )
     button:addEventListener"tap", ClickSound )

     next:addEventListener"tap", changeScenes ) 
     next:addEventListener"tap", ClickSound )

 

 So i would like to explain what i am doing currently is that i have assigned this TransitionFunc function to the button. Whenever the button is pressed it adds + 1 to the tap Count variable and then the if/elseif structure compares the value to tapCount, depending on the value the previous text and sprite is hidden by alpha = 0 and new sprite and dialogue is generated/visible by transition.to alpha = 1.

Q1)Now i am having a feeling that this might be a poor way of doing things. And i needed your help on how to incorporate Constructors and parameters to control repetitive tasks.

 

Q2) Is there anyway that i could declare a method of transition.to without parameters and then specify the object, time, and delay later to save lines of repetitive code.

Q3) If anyone has a better logic for a way of doing dialog and character transitions please kindly share with me so that i can structure my thing better. 

Your help will be very much appreciated guys, help a brother out.


Thank you



[TOPIC: post.html]
#2

schizoid2k

[GLOBAL: userInfoPane.html]
schizoid2k
  • Contributor

  • 567 posts
  • Corona SDK

It looks like this function makes text objects appear/disappear depending on a value.  If that is the case, I would just declare another function to do the animation.

 

Some untested code...

function AnimateText(object, alpha, time)
    transition.to(object, {alpha = alpha, time = time})
     
    -- whatever else
end

function TransitionFunc()
    tapCount = tapCount + 1

    if tapCount == 1 then 
        AnimateText(Dialogtext, 0, 800) 
        -- other animations, if needed
    end

    -- etc, etc
end


[TOPIC: post.html]
#3

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,861 posts
  • Corona SDK

Certainly the way you're doing it will get very convoluted when you're up to tap count 400 and have to remember what needs to be hidden and shown. You'll need to make use of tables, that contain data about each line, such as the text, who says it, any images that need to be shown etc, sounds to be played. 

 

So you could split up your game into a series of conversations, each containing a number of 'lines'. Draw your DialogText, NameText objects once in scene:create() and keep a reference to them at the top of the scene, and then amend the text based on the next line.

 

A very rough outline:

 

 
-- conversations.lua
 
local m = {}
 
m[#m+1] = { backgroundImage = "forest.jpg", lines = {}} -- a new conversation
 
m[#m].lines[#m.lines+1] = {name = "Kamali", text = "What day is it, again?", image = "kamaliConfused.png"}
m[#m].lines[#m.lines+1] = {name = "Kamali", text = "Tuesday?"} -- no image, we'll continue with previous one
m[#m].lines[#m.lines+1] = {name = "Sarah", text = "Yeah, I think so..?", image = "sarahShrugs.png", sound = "laugh.mp3"  }
 
m[#m+1] = { backgroundImage = "cinema.jpg", lines = {}} -- a second conversation
 
m[#m].lines[#m.lines+1] = {name = "Simon", text = "Hmm, how did we get here?", image = "simon.png"}
 
return m
 
 
-- myGame.lua
 
local conversations = require("conversations")
 
local currentConversation = 1
local currentLine = 1
 
 
local displayNextLine = function ()
 
  local line = conversations[currentConversation][currentLine]
  
  
  DialogText.text = line.text
  NameText.text = line.name
 
  if (line.image ~= nil) then
    -- set my image fill here
  end
  
  if (line.sound ~= nil) then
    -- play sound here
  end
  
  currentLine = currentLine + 1
  
  if (currentLine > #conversations[currentConversation].lines) then
    currentConversation = currentConversation + 1
    currentLine = 1
   -- do anything else we need to after a conversation finished
  end
  
 
end
 
local setupConversation = function ()
   
   -- change background image here, and anything else before a new conversation starts
 
end
 
 
local TransitionFunc = function ()
  
    if (conversations[currentConversation] == nil) then
      print ("No more conversations to show...")
      return
    end
 
   if (currentLine == 1) then
    setupConversation()
   end
   
    displayNextLine()
     
  
end
 
button:addEventListener( "tap", TransitionFunc )
 

  • sporkfin likes this

[TOPIC: post.html]
#4

sani3798

[GLOBAL: userInfoPane.html]
sani3798
  • Observer

  • 4 posts
  • Corona SDK

Firstly @Nick Sherman, @schizoid2k  thank you guys for taking the time to reply and taking the time to write sample code to help me out.

I tried Nick's code, basically i have 3 lua files in the game folder right now. Conversation.lua, game.lua and main.lua all connected with composer.api.

 

----Game File-----

 

-----------------------------------------------------------------------------------------
--
-- game.lua
--
local composer = require"composer" )

local conversations = require("conversations")

-----------------------------------------------------------------------------------------

-- Your code here

local currentConversation = 1
local currentLine = 1

local DialogText
local NameText

local K3
local button

local TransitionFunc = function ()
  
    if (conversations[currentConversation] == nilthen
      print ("No more conversations to show...")
      return
    end
 
   if (currentLine == 1then
    setupConversation()
   end
   
    displayNextLine()
end

function scene:createevent )
    local sceneGroup = self.view

  function DisplayNextLine()

    local line = conversations[currentConversation][currentLine]
  
    DialogText.text = line.text
    NameText.text = line.name
 
    if (line.image ~= nilthen
    -- set my image fill here

    --Kamali's Second pose
    K3 = display.newImageRect( sceneGroup, "SceneAssets/klab6.png"260380 )
    K3.x = display.contentCenterX + 180
    K3.y = display.contentCenterY
    K3.alpha = 0

    --Button
    button = display.newImageRect( sceneGroup, "SceneAssets/blue.png"4040 )
    button.x = display.contentCenterX + 250
    button.y = display.contentCenterY + 120
    button.alpha = 0

    end
  
    currentLine = currentLine + 1

    if (currentLine > #conversations[currentConversation].linesthen
        currentConversation = currentConversation + 1
        currentLine = 1
       -- do anything else we need to after a conversation finished
    end

    button:addEventListener"tap", TransitionFunc )

  end
end

-- show()
function scene:showevent )
 
    local sceneGroup = self.view
    local phase = event.phase
 
    if ( phase == "will" ) then
        -- Code here runs when the scene is still off screen (but is about to come on screen)
 
    elseif ( phase == "did" ) then
        -- Code here runs when the scene is entirely on screen
 
    end
end

-- hide()
function scene:hideevent )
 
    local sceneGroup = self.view
    local phase = event.phase
 
    if ( phase == "will" ) then
        -- Code here runs when the scene is on screen (but is about to go off screen)
 
    elseif ( phase == "did" ) then
        -- Code here runs immediately after the scene goes entirely off screen
 
    end
end
 
 
-- destroy()
function scene:destroyevent )
 
    local sceneGroup = self.view
    -- Code here runs prior to the removal of scene's view
 
end
 
 
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener"create", scene )
scene:addEventListener"show", scene )
scene:addEventListener"hide", scene )
scene:addEventListener"destroy", scene )
-- -----------------------------------------------------------------------------------
 
return scene

 

-----conversation file-------- (Didnt throw in everything yet just for the sake of simplicity and trying the suggested structure)

 

-----------------------------------------------------------------------------------------
--
-- conversations.lua
--
-----------------------------------------------------------------------------------------

-- Your code here

local m = {}
 
m[#m+1] = { backgroundImage = "SceneAssets/Lab_bg1.png", lines = {}} -- a new conversation
 
m[#m].lines[#m.lines+1] = {nameText = "Sarah", text = "What day is it, again?", image = "SceneAssets/KamaliLab2.png"}
m[#m].lines[#m.lines+1] = {nameText = "Kamali", text = "Tuesday?"-- no image, we'll continue with previous one
 
return m

 

 

------main.lua-------

 

-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

-- Your code here

local composer = require"composer" )
composer.gotoScene"game" )

 

So i get a compile time error that i am not specifying the length of lines correctly. Attempt to get length of field lines (a nil value) stack traceback. Perhaps i am doing something wrong, apologies if i am being too nooby, i am new to Lua and Corona all together.



@Schizoid2k

Thanks for your input. I did try making a function the way you suggested. The issue which comes is if i call a function within a specific tapCount, lets say i call it when (tapCount == 1), what happens is before the dialogueText is updated with new Dialogscript, the function call hides previous text and displays next text within the function call, so if i paste it before my dialogueText = display.newText, the function never picks up the updated dialogueText.. and if i paste it after, i end up having none of the dialogues disappearing and end up having overlapping dialogues on top of one another.

 

function dialogFunc()
    --Dialog Disappear
    transition.to( DialogText,{ alpha = 0, time = 800 } )
    --Dialog Appear
    transition.to( DialogText,{ alpha = 1 ,time = 800, delay = 600 } )
 end

 

 

function TransitionFunc()

    tapCount = tapCount + 1

    if(tapCount == 1then    
        --Dialog Text for Kamali
        DialogText = display.newText( dialogScript[1] , 245280"SceneAssets/GeoSansLight"14)
        dialogFunc()
        ButtonAppearDisappear()

 

 

Also is there a way to check how much memory or resource intensive my code is getting? I googled and found a method on stack overflow which shows garbage collection however i am not sure if i implemented it correctly with my code as it didnt work earlier. 

 

Can post my full github repository link here if maybe that helps to look at my code better for you guys.

Thanks again for the help, really appreciate it fellas.



[TOPIC: post.html]
#5

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,861 posts
  • Corona SDK

Apologies, each line of dialog should be added like this:

 

 
m[#m].lines[#m[#m].lines+1] = {name = "Kamali", text = "What day is it, again?", image = "kamaliConfused.png"}
 
 
I did it this way so if you want to insert/remove conversations, or lines in the middle of conversations, you don't have to go around renumbering everything. 
 
What we're doing is:
 
m[#m] - grab the last element added in the 'm' array.
 
.lines - access the lines table of that element so we can add to it
 
[#m[#m].lines+1] - grab the last element again so we can count how many lines already added, and add one to get the index to set in the lines table with whatever follows.



[topic_controls]
[/topic_controls]