How do you plan your code?

I am interested in remaking some old DOS games! Mostly for myself and my siblings to play and me to learn to code better, and it is easier for me to start by copying things before making my own

However, I am far from that point.
So here are some Questions!

  1. I’m not sure how and where I should be saving things like what each screen actually looks like. Should I be using classes or just giving them their own little functions… And what goes in setup()? Obviously only one screen should be displayed at a time and I would like too write the code for this properly

And the game logic. Like, if you hit turn then the following events happen, increment the game date and handle all the other stuff, and transition to different scenes… Probably going in its own class I think!

I’ll also need to know how to comment nicely to keep the code from devolving into a mess six months from now. Any thoughts on this?

These are some of my planning questions

For later: the real meat and potatoes, the part of the code that actually makes the game to play (which I haven’t even started yet) and the AI (I expect this to be the hardest part, if I ever reach it)

Since this is going to be a big project for me, I was wondering if you had some tips on how to organize code. And yes, I fully expect to screw up along the way. I am afraid of writing bad code and then throwing it all out but I am also a beginner so that’s probably going to happen regardless.

My advice would be start simple and work up. Try not to tackle something too big to start with and there is a real danger of disengaging.

There are a few starter projects on the wiki such as snake, lunar lander and asteroids to get you started (https://bitbucket.org/TwoLivesLeft/core/wiki/Step%20by%20step%20projects)

Specifically addressing your questions - you should look into finite state machines- there are a few examples out there.

Finally, I would strongly urge you to take a look at @Ignatz site - he has a wealth of information on Codea there https://coolcodea.wordpress.com/2013/03/10/starting-with-codea/

When you have multiple screens, quite a neat way to code them is like this. It means you can code each screen completely separately, and there is no need for a big mess of code and if statements in the draw function.

--start by writing code to draw each screen separately
function DrawIntro()
    --code to draw intro screen
end

function DrawMenu()
    --code to draw menu
end

function DrawLevel1()
    --code to draw level 1
end

--create a variable to tell Codea which one to use
drawScreen=DrawIntro --to draw the intro screen

--then in the draw function, you simply write
drawScreen()

--when the intro is finished, you can start drawing the menu screen with
drawScreen=DrawMenu
--and there's no need to change anything in draw

--and when you start level 1, you can begin drawing it with one command
drawScreen=DrawLevel1

Very Nice, @Ignatz I will definitely be doing that. Thanks for the tip.

@West Indeed I am learning about finite state machines. For the menu stuff I will certainly be using one.

And for the rest of the game logic, well… Planning!

@xThomas do yourself a favor and comment code! Every class method, every algorithm and every touch-checking-event. you will profit from it in the long-run. and backup your project frequently.

example 1:
i often forget, why some of my methods even accept variable number of args={...}, then i always have to spend some minutes trying figure out what goes where, to understand it again. comments help out here.

example 2:
i had a project with a giant codebase. one day codea crahed, while i was working on it through air-code, and i lost almost everything. now i have a tool, thats making backups of my project automatically (at time intervals). have always a copy of your code!

Don’t try to do something big beyond your current programming experience. Write small programs that do simple things, then re-write them trying to make it smaller. Try using different commands and play with them so you become familiar with what they can and can’t do. Look thru the reference so you become familiar with what’s available to use. It’s hard to write code if you don’t know what you can do. Load example programs from the forum, see what they do, them look thru the code and try to understand why it’s working. If you try to write some game from the past that took several people months to write, chances are your going to fail and give up with coding. Keep it small, have fun, and build up you knowledge without getting frustrated.

@Ignatz

I use a button class where I would write mybutton = button(text,x,y) in setup and then call mybutton:draw() in draw and mybutton:touched(touch) in touched.

I don’t know how to use this in your example with just CurrentScreen=myscreen()

-- FINITE STATE MACHINE 

function MenuScreen()
    back = sprite("Documents:Artifact Two", WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
    option = button("OPTIONS", vec2(WIDTH/2, 550), 225, 80)
    option:setColors(color(125), color(125), color(50, 205), color(50, 205))
    option:textOptions("ArialRoundedMTBold", 42, color(0))
end

function setup()
    CurrentScreen=MenuScreen
end

function draw()
    CurrentScreen()
end

function touched(touch)

end

If myscreen() is your menu drawing function, then

function myscreen()
    background(200)
    --any other code you want
    mybutton:draw()
end

In other words, treat myscreen() as your draw function and put all the code in there that you would write if you were only going to draw a menu and nothing else.

You need a similar system for the touched function, ie write a separate version for each of the screens, like this

--in setup
CurrentTouched=TouchedMenu()

function touched(t)
    CurrentTouched(t)
end

function TouchedMenu()
    --the code you need to deal with menu touches
   --maybe it includes code to start playing, eg

   --if start button touched, then
   CurrentScreen=DrawPlaying --where DrawPlaying draws the playing screen
   CurrentTouched=TouchedPlaying
end

Can you see? Touched works just like draw.

So instead of having a pile of code in draw and touched that say “if the state is menu, do this, else if it is play then do that, else if …”, you have as little as one line of code. Then you write individual draw and touched programs for each state. It is so much easier to write and test code, when you only have to do it for one state at a time and can ignore all the others.

Similar to @Ignatz suggestion, I would suggest you extend MenuScreen to have methods.

This pattern is called a “singleton”, meaning an object of which there is only ever one instance.

eg:

-- FINITE STATE MACHINE 

MenuScreen = {} -- an empty table to hold methods

--put as many methods as you need in it

function MenuScreen.init()
    -- setup code
end

function MenuScreen.draw()
    back = sprite("Documents:Artifact Two", WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
    option = button("OPTIONS", vec2(WIDTH/2, 550), 225, 80)
    option:setColors(color(125), color(125), color(50, 205), color(50, 205))
    option:textOptions("ArialRoundedMTBold", 42, color(0))
end

function MenuScreen.touched(touch)
    --touch logic
end

function setup()
    CurrentScreen=MenuScreen
    CurrentScreen.init()
end

function draw()
    CurrentScreen.draw()
end

function touched(touch)
    CurrentScreen.touched(touch)
end

Good idea B)

Hi @xThomas,

Generally you want to do an up front design of all the elements you are going to need, and roughly work out their interactions and the object types…

Anything you create multiple instances of should generally be a class() (characters, enemies etc.), any ‘helper’ or global functions should be in a global table or actual Singleton class e.g. Views, levels

You should generally only have draw(), setup() and touched() as global functions, everything else should live in a class or global table so you can ‘classify’ functionality and not pollute the global namespace, e.g.

Utility = {}

Utility.WaterDepth = 3

function Utility.isUnderwater(level)
    return level < Utility.WaterDepth
end

All constants, strings, numbers etc. should be in either a Constants table, or should be as class ‘statics’ e.g.:

TerrainBlock = class()

TerrainBlock.Type = { Rock=1, Grass=2, Water=3}

function TerrainBlock:init(type)
    assert(TerrainBlock.Type[type], "Unknown type: " .. type)
    ...
    ...
end

myBlock = TerrainBlock(TerrainBlock.Type.Rock) 

Clean structure and design allows you the best chance of not getting part way through then having to rewrite core objects or ‘bend’ your design to breaking point…

Cheers,
Brookesi