Log In  
Follow
Snow_
Follow

I design and code games part time (though I wish I could do it full time).

Cart #ultra_simple_platformer-0 | 2021-03-08 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
10

Demo:

Same base engine used in Bullet Ball:

This platformer base code is what my game Bullet Ball is built on. It is inspired by Super Mario Bros for the NES. This demo contains code for Super Mario style variable jumping, AABB collision (1 way platforms or full collision), and a very simple animation function.

Like many newbies, I struggled with platforming when I was learning to program and always found that my code was bloated with many unnecessary variables. I still see many newbies struggling with this. I'm also seeing many demos with verbose code and needless multiple variables.

Programming is difficult and optimizing even more so, but as a rule of thumb, you always want to have efficient, optimized code that's clear to read and understand. By efficiency, you want to use as little computer power as you can. Even though with today's ultra blazing fast processors, it seems not necessary, it's a good practice, because it also helps you simplify. It takes years to get there, but you learn.

The magical element in my code is the use of lookup tables for the use of movement and position for collision detection. Super Mario Bros used lookup tables as using mathematical equations (especially multiplication and division) would bog down the program on the NES. The NES ran at 1.79MHz with very limited ram. NES programmers had to optimize hardcore to get their games to run the way they wanted them too. SMB is a true marvel. In my own movement code, I only increment, decrement and use modulus (same as division, but the result is the remainder) for friction.

So, a quick look at the lookup tables and an explanation for them. Following that in the hidden tag is commented code. It is aimed at newbies with little experience coding. The code in the demo above is condensed down to 87 lines (sans the 2 dividing dashed lines) and can be condensed a bit more if you take out the block for 1-way platforms.

This is the speed look up table. This is used for both horizontal running and vertical jump movement.

speed={-4,-2,-1,-1,0,1,1,2,4}

By using a counter variable that can increment or decrement, I can then add the result to my x or y position and voila.

For example, if you wanted the player to just run right at top speed:

hv=9 --hv is horizontal velocity
x+=speed[hv]

So by simply changing the hv variable, I can make the player not only move left or right, but also immitate acceleration and drag. Notice how the sets of numbers count up on both sides of 0. Look at the movement function in the code below to see how this all works.

For gravity, using the speed table is super handy. If vv (vertical velocity) is less than 5, my player will move up (jumping), but go past 5 and the player starts to fall. So in my movement code, I have:

if(vv<9) vv+=1

This line runs no matter what. When holding down my jump button, vv is set to 1 and will be reset at 1 every tick until either my jump boost (see code below) runs out or I let go before it runs out, so that the player will move up. When I let go or my jump boost has hit max, then the line above is free to count up vv. This causes an arc movement and then the player falls down and will continue to move down unless stopped by a platform. Gravity.

My 2nd look up table is simply a table of multiples of 8:

for i=-1,16 do
    tile[i]=i*8
end

This table helps in detecting local collision around the player. Refer to the code below to see how it works.

Feel free to use the code as a base for your projects. Be careful if you tinker with the values within the speed table. Collision can be easily thrown off and you might end up inside or going through blocks. I'm not easily available, but I'll answer any questions best I can, when I can. I'm also of the "there are no stupid questions" policy. Ask anything.

You can also look at the code in Bullet Ball to see more platformer functions and to see how my code works with the entire map space. At the moment BB's code is uncommented, but I am putting together a post-mortem post that will contain commented code.

FULL COMMENTED CODE:

-->8
--player variables
x=60
y=88
xdir=false 

--movement variables
hv=5 --horizontal velocity
vv=5 --vertical velocity
friction=0
surface=2 --works as a counter with friction.. the higher the number, lower the friction
boost=0 --variable jump height counter
speed={-4,-2,-1,-1,0,1,1,2,4} --this is the speed look up table. it can be used for left/right and vertical movement.

--map variables
tile={} 
for i=-1,16 do
    tile[i]=i*8 --look up table with multiples of 8 (8*-1 to 8*16). this is used in the collision function for horizontal and vertical coordinates.
end
--animation variables
anim=false 
set=2 --the first sprite of the current set of frames to animate.
start=0 --this works as a counter with duration.
duration=3 --length of current set of frames
frame=1 --starting frame

--test timer variables
timer=0
timerlimit=20 

-->8
function _update()
    --timer=(timer+1)%timerlimit
    --if timer==0 then
        input() 
        move() 
        animate() 
    --end
end

function input()
    if btn(0) then --if pressing "left", face left, count down horizontal velocity
        xdir=true 
        if(hv>1) hv-=1 
    elseif btn(1) then --"right", face right, count up horizontal velocity
        xdir=false 
        if(hv<9) hv+=1 
     else 
        friction=(friction+1)%surface --when friction%surface is 0, then if moving horizontally, count up or down until hv is 5
        if friction == 0 then
            if(hv<5) hv+=1
            if(hv>5) hv-=1
        end
    end
    if btn(5) then
        if boost < 6 then --variable height jump
            boost+=1 
            vv=1 --so long as boost is less than 6, keep vertical velocity at 1. speed[1]=-4, so the player will continue moving up 4 pixels
        end
    else
        boost=6 --if let go in mid air, set to 6 to prevent double jumping. resets to 0 when on ground
    end
end

function move() --here is where the speed look up table is used for both horizontal and vertical speeds
    x+=speed[hv] 
    y+=speed[vv]
    if(vv<9) vv+=1 --unless vv is set by another function, it will otherwise count up till 9. here is where the jump arc happens and then constant gravity.
    collision()
end

function collision()
    anim=false --at the beginning, anim is false - this way, unless player is touching ground, player will display jump sprite.
    surface=4 --setting at 4 at the beginning allows for more natural movement in air. on ground is set to 2.
    if(x>=120) x=120 --set right side screen boundary
    if(x<=0) x=0 --set left side screen boundary
    local n1=flr(x/8) --n1 and n2 get the coordinates of the tile that the top left pixel of the player is currently inhabiting.
    local n2=flr(y/8)
    for i=n1-1,n1+1 do --now we check all the tiles around the player. in this code, this is extended 2 tiles below the player.
        for j=n2-1,n2+2 do
            if fget(mget(i,j),0) then

                --uncomment this block if you want one way platform collision------
                --[[if x < p[i]+7 and x+7 > p[i] and y <= p[j-1] and y+8 >= p[j-1] and vv>5 then 
                    -- if y < p[j] and y+8 >= p[j] then
                        -- if (not btn(5)) boost = 0
                        -- y=p[j-1]
                        -- vv=5
                    -- end
                end]]
                -------------------------------------------------------------------                         
                --this block of code allows for full aabb collision---------------- 
                --top of tile
                if x < tile[i]+7 and x+7 > tile[i] and y < tile[j] and y+9 >= tile[j] and vv>5 then --note that the 'tile' look up table is used here.
                    if (not btn(5)) boost = 0 
                    y=tile[j-1] --set player position on ground
                    vv=5 --stop vertical movement
                    anim=true --now on ground, anim is true
                    surface=2 --add more friction to movement now that on ground
                end
                --bottom of tile
                if x < tile[i]+7 and x+7 > tile[i] and y-1 <= tile[j]+7 and y+7 > tile[j]+7 then
                    if(vv<9) vv+=1 --incrementing vv here doubles time for movement to go from up to down.
                    boost=6 --set to 6 to cancel jump
                    y=tile[j+1]
                end
                --right side of tile
                if x-1 <= tile[i]+7 and x+7 > tile[i]+7 and y < tile[j]+7 and y+7 > tile[j] then 
                    hv=5
                    x=tile[i+1]
                end
                --left side of tile
                if x < tile[i] and x+8 >= tile[i] and y < tile[j]+7 and y+7 > tile[j] then 
                    hv=5
                    x=tile[i-1]
                end
                --------------------------------------------------------------------
            end
        end
    end
end

-->8
function animate()
    if anim then 
        if(hv~=5) then
            start=(start+1)%duration --when anim is set to true and hv is not 5, then run the 'running' animation
            frame=start+set
        end
        if(hv==5) frame=0 --if hv is 5, then set frame to 'stand' frame
    else
        frame=4 --otherwise set to jump frame
    end
end

function _draw()
    cls()
    map(0,0,0,0,16,16)
    spr(1+frame,x,y,1,1,xdir) 
end

P#88071 2021-03-08 21:01 ( Edited 2021-03-09 04:03)

Cart #bullet_ball-0 | 2021-02-26 | Code ▽ | Embed ▽ | No License
3

Welcome to Bullet Ball.

Once upon a time, cute and fluffy street thugs decided to settle a score they had with a friendly round of street ball. Their skirmishes grew intense and it wasn’t long before weapons got involved. Their game of street ball evolved into Bullet Ball. Since then, they’ve forgotten why they were even fighting and continue their battle today.

The object of the game is to get the ball into the opposing team’s hoop. You will have an arsenal of 8 weapons and power ups to aid you or your team to victory.

Current Version Notes:


Well, I was able to move BB out of the WIP section a lot sooner than I hoped. I went on a bug squashing rampage in the last 2 days, but found no bugs.. rather just 2 undesired effects which have been remedied. So far, the code is good. It's also literally at 8192 tokens. Unless I do any further optimization to free up say 10 to 20, there is no point. At this point, if any updates are needed, they should be small and quick to add.

The current code lacks comments. I'm redoing them all, and hope to release commented code in the near future in a separate "post mortem" post. On that note, I am also preparing a tutorial post (sitting in drafts) for newbies, which will demo and go over the code for the base, barebones platformer code that BB is built on. It is a very simplified - movement/variable jumping/aabb collision/animation bit of code. It can be condensed down to probably 60-70 lines. Exciting!

I still have not been able to test 4 player yet. I have a USB adapter that allows for 4 NES controllers to be hooked up, but so far am only able to get the first 2 working only with Joy2Key.

Feel free to post gifs of your gameplay. Also, I will need the communities help to test my maps. So constructive criticism is highly appreciated. Definitely build maps in the map editor and also post pics of your favorites. Map making in multiplayer games is a community effort as everyone plays a bit differently and enjoys differing levels of difficulty. So getting that balance in default maps will be an ongoing effort.

Default controls:

P1: up (aim) down (aim) left (aim/move) right (aim/move) z/n/c (fire/toss) x/m/v (jump)
P2: e (aim) d (aim) s (aim/move) f (aim/move) TAB/L Shift (fire/toss) q/a (jump)
P3-P4: Configure your controllers how you wish.
WARNING: 4 player has not been tested with controllers yet.
You can aim in 8 directions.

Ctrl+R will instantly reset the game.
WARNING: if you reset your game and you made a custom map with the map editor, it will default back to the skeleton map. You will have to rebuild it. If you want to leave your current round, but keep your custom map, press ENTER and select "exit round". This will reset the game, but map selection will still have your map as the first one.

Starting a Game

At the menu screen, when selecting 2 or 4 player, you will instantly open up to the game screen where pressing left or right will scroll through the levels. The default characters are already in their spawn positions. Select a map by pressing X.

All players can then choose their character by pressing up or down. You can choose one of the following 4:

[8x8]
Fluffy the bunny
[8x8]
Muffin the mouse
[8x8]
Stubbs the dog
[8x8]
Patchy the cat

Each player must press X for the game to start. This is indicated by the X symbol above each player. They disappear, once a character is chosen.

Gameplay

Get the ball in the opposing team’s hoop. The first to score 10 points wins the round.

You can only hold one item: the ball or a weapon. Once a weapon is discarded, either by touching the ball, using up ammo, or tossing it (knife and star), another weapon will immediately spawn in a random position on the map.

Powerups will also randomly spawn on the map after some time. All powerups restore 1 heart of health. Special powerups spawn less frequently, but will give the player full health and invincibility for 5 seconds, if the powerup matches the character:

Fluffy – carrot
Muffin – cheese
Stubbs – chicken leg
Patchy – fish

You have 3 hearts of health. If you lose all 3, you die and respawn. When you respawn, you are invincible for 1 second.

There are also 2 features that can aid in a victory:

Using The Map Editor

Press Z to bring up your editor panel and press Z again to hide it.
Press X to make your selections

Use arrow keys and X to design your map. You can erase a tile, simply by moving the cursor onto it and pressing X.

You can mix and match your tiles. You have a lot of freedom in the editor so be creative and have fun. Just remember, that if you want to share maps (via image post here), make sure they are symmetrical, so that both sides have equal chance.

NOTE: Leave at least 2 open vertical spaces at the first column of tiles (left of screen) and last (right of screen). The game code picks these spaces as spawn areas. If you make a column of blocks from the floor up to the block that holds the hoop, with no spaces, the players will end up spawning inside the blocks. This may cause a crash or other unintended effects.

FILL will set all the visible tiles to whatever tile you have selected.
SAVE will activate the map and add it to the beginning of the map list.
EXIT will go back to the main menu. If you saved your map and start a new game, your custom map will be the first choice.

P#87690 2021-02-15 22:23 ( Edited 2021-02-26 19:13)

Follow Lexaloffle:        
Generated 2021-09-28 02:35:13 | 0.069s | Q:13