2d sidescroller engine in progress: DKC2 remake. Test dev.

Started by LemonWizard, January 01, 2012, 03:30:37 AM

Previous topic - Next topic

LemonWizard

Hey all.
Well as you all know by now , or should. I like to push things with playbasic, past the limits.
IT SHOULD be capable of running a game that's created in snes style.

For all you retro gamers out there, the wait is over.
I'm finally (after years of saying I can/will) creating a fully functional 2d sidescrolling system.

It will feature a comprehensive in game editor, and it will also feature sprite placement and tools for setting collision events.
Hopefully down the road it will have a trigger system and some kind of a scripting system, where you can add already made scripts as well for sprites.
Such as AI and paths.
I don't just plan on going half way either. This engine is going to be completely developed, into a fully functional game engine.
Which, should when completed be adaptable to build almost any type of game on. With a few adjustments of course.

So far the global variables that are the most important are the map sizes, and the sprite width and height.
The collision system uses 16*16 tiles, and right now it does not draw images as tiles but instead renders a large tiled image, from a file.

Basically the collision system lets you point and click where you want your "solids" to go. And the engine handles the rest. Simple.

Without further delay here is the screenshot.
I can't promise I'll be able to live up to even my own expectations Just recently I had a nasty hard drive error. Making backups tonight to be safe!!


LemonWizard

Update and backup of code:

PlayBASIC Code: [Select]
; PROJECT : Castle Crush
; AUTHOR : NA
; CREATED : 12/27/2011
; EDITED : 1/1/2012
; ---------------------------------------------------------------------
castle=loadnewfximage("castlecrush.png")
imagemaskcolour castle, rgb(255, 0, 255)
mode=loadnewfximage("mode.png")
HEIGHT=getimageheight(castle)
WIDTH=getimagewidth(castle)
save=loadnewfximage("save.png")
playmode=loadnewfximage("Playmode.png")
grid=false
backdrop=loadnewfximage("castle.png")
levelname$="castle crush"
wall=loadnewfximage("wall.png")
wallx=0
wally=12256-200



dim dixieright(18)
dim dixieleft(18)
for temp=1 to 18
dixieright(temp)=loadnewfximage("Sprites/dixieframe"+str$(temp)+".bmp")
imagemaskcolour dixieright(temp), rgb(255,255, 255)
dixieleft(temp)=newfximage(55, 45)
copyimage dixieright(temp), dixieleft(temp)
mirrorimage dixieleft(temp), 1, 0
next temp


dim dixiejumpright(4)
dim dixiejumpleft(4)

for temp=1 to 4
dixiejumpright(temp)=loadnewfximage("Sprites/dixiejump"+str$(temp)+".bmp")
imagemaskcolour dixiejumpright(temp), rgb(255, 255, 255)
dixiejumpleft(temp)=newfximage(55, 74)
copyimage dixiejumpright(temp), dixiejumpleft(temp)
mirrorimage dixiejumpleft(temp), 1, 0
imagemaskcolour dixiejumpleft(temp), rgb(255, 255, 255)
next temp



dixieaction=1
jumpframe=1



SCROLLX=0
SCROLLY=11776
MAPWIDTH=roundup(WIDTH/16)
MAPHEIGHT=roundup(HEIGHT/16)
dim map(MAPWIDTH, MAPHEIGHT)
spritewidth=55
spriteheight=45
dixieframe=1
frametimer=timer()+30

type solid_tile
x1
y1
x2
y2
endtype


dim solids(MAPWIDTH, MAPHEIGHT) as solid_tile
read=false
if fileexist("C:\\castlemap.txt") then read=true

IF READ=TRUE
readfile "C:\\castlemap.txt", 1
rendertoimage castle
for tempx=1 to MAPWIDTH
for tempy=1 to MAPHEIGHT
map(tempx, tempy)=readint(1)
solids(tempx, tempy).x1=readint(1)
solids(tempx, tempy).y1=readint(1)
solids(tempx, tempy).x2=readint(1)
solids(tempx, tempy).y2=readint(1)
x1=solids(tempx, tempy).x1
y1=solids(tempx, tempy).y1
x2=solids(tempx, tempy).x2
y2=solids(tempx, tempy).y2
ink rgb(0, 0, 255)
box x1, y1, x2, y2, 0
next tempy
next tempx
closefile 1

ENDIF


myimage=newfximage(640, 480)
imagemaskcolour myimage, rgb(255, 0, 255)
MODE$="View"


rendertoimage castle

if grid=true
for tempx=1 to WIDTH/16
for tempy=1 to HEIGHT/16
ink rgb(255,255, 255)
box (tempx-1)*16, (tempy-1)*16, tempx*16, tempy*16, 0
next tempy
next tempx
endif


wallspeed=25
charx=400
chary=12128
falling=false
walltimer=timer()+wallspeed


do




if timer()>walltimer
walltimer=timer()+wallspeed

if falling=true
if chary=>wally-spriteheight-1
chary=wally-spriteheight-1
landed=true
falling=false
onwall=true
else
onwall=false
endif
endif




if jump=false
if falling=false
if onwall=true
chary=chary-1
endif
endif
endif
Login required to view complete source code



I am not sure if I want to upload a full demo yet. It isn't in completely working order the way I'd like.
IF ANY retro game fans want to help me with this project let me know. WE CAN build on this game engine together :D I'm sorry about the poor camera code. it was the only way I could break playbasic's tile scrolling limits without using scenes or cameras that are built into it's engine.
The player's X and Y coordinates are drawn by adding the scrollx and scrolly values to the calculation since drawing the player directly onto the castle image, OR making a copy of the castle image does NOT work. And the player MUST be drawn using world coordinates or collision will fail.




ATLUS


LemonWizard

#3
Oh my god so I stayed up again all night tinkering with the engine.
I'm going to have some fun, creating a few non dkc2 images and using the collision data to test a few things.
I've improved a few things and tested a few things. UHM
here's a list


  • Player has been measured to jump 4 tiles high.
  • Save feature blocks versus regular blocks are different colors  
  • Wall code was commented out in this version due to glitching
  • Players hitbox has been shrunk down to a more fitting size
  • Slight optimization in drawing routine. Nothing much
  • The transparency for both the temporary image and the working map image has been changed from 255, 0, 255 to 255, 255, 255 (white)
  • The working image file is now called castle2.png and is going to be a template for testing.

TODO:


  • Create a way for changing the backdrop image through the editor rather than direct code
  • Create a sprite system which imports sprites
  • Make it so that the hitbox per frame of a sprite can be set
  • Allow the editor to set the players start location and save it, to the map file
  • Create a seperate file, for the level called enemies.txt which saves sprite locations
  • Allow the editor to have a variety of hitbox sizes all in the same level
  • Create a special sprite which can use any image or animation sequence that represents a door or exit
  • Create the ability to use an on collision with event, for an object of type "exit"
  • Create a selection tool which sets the 'exit on collide' flag, to the next level which can be selected when edited
  • Import multiple backdrops
  • Modify interface, and add a sub menu which exists on another screen for convenience
  • Fix a bug which renders too much of the backdrop to the screen past the 480 mark.
  • Fix some collision bugs and account for the bottom of all platforms in the collision routine
  • Change the players object to use types for it's data.
  • Create a mini editor which lets someone set up a type for an object which is initialized as a custom type in playbasic

Note: THIS ISNT ALL OF IT

LemonWizard

#4
OK so I'm going to end up updating this to be semi multiplayer.
I'm considering changing the engine around and adding a forces property , or a set of forces property to in game objects.
So that, when objects collide I can check force against xyz.

Not sure yet. I'll be testing local multiplayer first, maybe. .. :/ one person can play as diddy, the other as dixie, that would be interesting :O

Ok I decided instead of fixing the camera I'm going to add the following items to the dkc2 engine today.
Bananas
Blast barrels
Hooks for the player to hang off of and jump using from hook to hook.
also adding in today
The ability for dixie to helicopter the way she can in the original.
This should make for a more interesting test level.

LemonWizard

#5
Update:

Checklist :

Bananas: Added
Better Gravity: Added (downward force or momentum integer only. )
Banana frames: added
Bananas are collectible: added
Dixie Spin attack. Dixie helicopter downwards (reduces current fallspeed by half, makes maximum fallspeed 2 instead of 4): Added

TODO:

create counter for bananas
Bananas are only randomized. Must change to user based placement.
Remove limit of only 300 bananas per level.
Import text for banana counter and have it display.
Add animations for balloons increase.
Add HUD : Balloons, Bananas, Coins.

LemonWizard






Current Code:

Posted for learning and observation purposes.
PlayBASIC Code: [Select]
; PROJECT : Castle Crush
; AUTHOR : NA
; CREATED : 12/27/2011
; EDITED : 1/4/2012
; ---------------------------------------------------------------------
castle=loadnewfximage("castlecrush.png")
imagemaskcolour castle, rgb(255, 0, 255) ;purpleish?
;imagemaskcolour castle, rgb(255, 255, 255) ;white
mode=loadnewfximage("mode.png")
HEIGHT=getimageheight(castle)
WIDTH=getimagewidth(castle)
save=loadnewfximage("save.png")
playmode=loadnewfximage("Playmode.png")
grid=false
backdrop=loadnewfximage("castle.png")
levelname$="castle crush"
wall=loadnewfximage("wall.png")
wallx=0
wally=12256-200
bananatimer=timer()+30
spinframe=1
spinframetimer=timer()+30




dim dixieright(18)
dim dixieleft(18)
for temp=1 to 18
dixieright(temp)=loadnewfximage("Sprites/dixieframe"+str$(temp)+".bmp")
imagemaskcolour dixieright(temp), rgb(255,255, 255)
dixieleft(temp)=newfximage(55, 45)
copyimage dixieright(temp), dixieleft(temp)
mirrorimage dixieleft(temp), 1, 0
next temp


dim dixiejumpright(4)
dim dixiejumpleft(4)

for temp=1 to 4
dixiejumpright(temp)=loadnewfximage("Sprites/dixiejump"+str$(temp)+".bmp")
imagemaskcolour dixiejumpright(temp), rgb(255, 255, 255)
dixiejumpleft(temp)=newfximage(55, 74)
copyimage dixiejumpright(temp), dixiejumpleft(temp)
mirrorimage dixiejumpleft(temp), 1, 0
imagemaskcolour dixiejumpleft(temp), rgb(255, 255, 255)
next temp

;load and flip dixie's spinning animations for hovering helicoptering


dim dixiespinright(10)
dim dixiespinleft(10)
for temp=1 to 10
dixiespinright(temp)=loadnewfximage("Sprites/dixiespin"+str$(temp)+".bmp")
dixiespinleft(temp)=newfximage(getimagewidth(dixiespinright(temp)), getimageheight(dixiespinright(temp)) )
copyimage dixiespinright(temp), dixiespinleft(temp)
mirrorimage dixiespinleft(temp), 1, 0
imagemaskcolour dixiespinright(temp), rgb(255, 255, 255)
imagemaskcolour dixiespinleft(temp), rgb(255, 255, 255)
next temp


dim bananaframes(8)
for temp=1 to 8
bananaframes(temp)=loadnewfximage("Sprites/bananaframe"+str$(temp)+".png")
imagemaskcolour bananaframes(temp), rgb(255, 255, 255)
next temp

type banana
x
y
frame
collected
endtype

dim bananas(300) as banana
for temp=1 to 300
bananas(temp).x=rndrange(0, 512)
bananas(temp).y=rndrange(0, 12256)
bananas(temp).frame=rndrange(1, 8)
bananas(temp).collected=false
next temp


dixieaction=1
jumpframe=1



SCROLLX=0
SCROLLY=11776
MAPWIDTH=roundup(WIDTH/16)
MAPHEIGHT=roundup(HEIGHT/16)
dim map(MAPWIDTH, MAPHEIGHT)
spritewidth=35
spriteheight=25
dixieframe=1
frametimer=timer()+30
maxfallspeed=4
falltimer=timer()+150 ;.5 miliseconds for falling increase

type solid_tile
x1
y1
x2
y2
endtype


dim solids(MAPWIDTH, MAPHEIGHT) as solid_tile
read=false
if fileexist("C:\\castlemap.txt") then read=true

IF READ=TRUE
readfile "C:\\castlemap.txt", 1
rendertoimage castle
for tempx=1 to MAPWIDTH
for tempy=1 to MAPHEIGHT
map(tempx, tempy)=readint(1)
solids(tempx, tempy).x1=readint(1)
solids(tempx, tempy).y1=readint(1)
solids(tempx, tempy).x2=readint(1)
solids(tempx, tempy).y2=readint(1)
x1=solids(tempx, tempy).x1
y1=solids(tempx, tempy).y1
x2=solids(tempx, tempy).x2
y2=solids(tempx, tempy).y2
ink rgb(0, 0, 255)
box x1, y1, x2, y2, 0
next tempy
next tempx
closefile 1

ENDIF


myimage=newfximage(640, 480)
imagemaskcolour myimage, rgb(255, 0, 255) ;purple ish?
;imagemaskcolour myimage, rgb(255, 255, 255); white
MODE$="View"


rendertoimage castle

if grid=true
for tempx=1 to WIDTH/16
for tempy=1 to HEIGHT/16
Login required to view complete source code


I'll post the actual demo now it's far enough along and I'm happy with it. Note: You'll need to paste in your own platforms using the editor feature.
Download link attached below!!


http://www.megaupload.com/?d=K3N1POX4

PLEASE reply to this post and leave your comments, questions etc. if you download the file, Please post! I want to know what you think :D :D

Instructions:

Play mode:
Up down left right (moves character)
UP: Jump
Space: While jumping, or falling: Spin/helicopter
Release space while helicoptering: Fall faster.

Collision mode:
up down left right (moves character)
UP: jump
Space : While jumping or falling: Spin/helicopter
note: You do not fall in collision mode
Mouse buttons: Left mouse: Place solid tile. For collision. Right mouse: move character

Enter key: Mode: ANY: reset character and camera to top of map/level

View mode: Nothing. But scroll. Click collision mode, or play mode, to play.

Note: You will have to place your own tiles through the map and then click save map if you want to reload it next time.

Other notes: Banans can not be edited in this version. But you CAN collect them. TRY TO GET THEM ALL :D
There is no counter for the bananas yet.
The jump height is exactly four collidable tiles tall. You can not jump any higher. It may have changed due to gravity physics being changed.
The rest should be straightforeward.
Note: In order to actually play, you have to click play mode in the menu.

If you begin falling off the very edge of the map at the bottom just press enter.

LemonWizard

I updated the camera with this code :


I got these values by taking my drawing surface size 640, 480.
Divide both by two.
Add the 640 to the scrollx so were looking at it's right edge, for the left side and how far away from the player it is from the camera, do the same to the scrolly.
Then leave the other values as they are because this time if the player is too far ahead of the camera's X1 coordinates and Y1 coordinates we move the camera foreward to catch up to the player. the other first two move the camera backwards
Since the drawing routine copies using scrollx and scrolly this works as a basic camera following AI. It's a little shaky needs some work. :D
PlayBASIC Code: [Select]
            if scrollx+640-charx>320      ;left side
scrollx=scrollx-3
endif

if scrolly+480-chary>240 ;top side
scrolly=scrolly-3
endif


if chary-scrolly>240 ;right side
scrolly=scrolly+3
endif

if charx-scrollx>320 ;left side.
scrollx=scrollx+3
endif




I also tried to put in 8000 bananas into my game loop.
The framepush function I have must be the thing lagging it out.
I have about 3 for temp loops already in my code, and they're all unique and all required.
Everything is as optimized as I can get it including a check which makes sure that it only asks against tiles that actually exist (gridlocked) for collision checks.

monkeybot


LemonWizard

Okay another update.
A bunch of stuff got changed and is still in the works.
I'm working on the camera right now. Fixed that.
I also fixed a few other things, and at the moment including the helicopter is more acurate to the original game mechanics.
You weren't able to helicopter at any point in a jump before, but now you can.
AND  , your fall speed gets reset to 1 when you do.
There's an update in the loop which checks the helicopter state, and updates the oldfallspeed as fallspeed.
fallspeed and the value which controls how fast you fall as your helicoptering are different, but fallspeed controls both the helicopter fallspeed and your original fallspeed.

Because helicopter fallspeed is derived from the fallspeed value then setting oldfallspeed=fallspeed in the update for the helicopter loop, as fallspeed is increasing each timer cycle it results we end up with the result of helicopterfallspeed=fallspeed/2. Uhm, and at the end of it if the helicopter loop is false, then the helicoptering ends and we end up with fallspeed=oldfallspeed, which basically appears to make you fall faster than you were while helicoptering, which is basically what happens anyhow.. but it makes sense to stop the fallspeed and reduce back to 1, once helicoptering starts. A flaw in the old version, which I wasn't doing or accounting for.

Physics gets interesting even basic physics.

Well, here's the new code. And uh, an upload. Oh a note: The level is now both horizontal and vertical and collision is account for in all directions. Camera centering is a bit buggy while placing tiles right click to drag camera around. Or use arrow keys. Next update will be made so camera only follows player when in play mode.
The jump height was also improved. Levels are larger.

http://www.megaupload.com/?d=401AGDX6


kevin


To be honest, i'm not really sure what the demo is meant to do, as all i see is a scrolling backdrop when in play mode (pictured bellow)..

After looking at the code, it's referencing at least one file that's not included in the archive.


kevin


  Had a look at the demo again, didn't initially realize that you're using a pre-rendered picture for the map ? - That picture is eating up some 25 meg of memory at run time and bloating the archive size.

  So attached is the level picture converted into a tile + block map.  At a block size of 32*32 there's only 91 unique tiles, weighing in around 400K.     

LemonWizard

#12
VIDEO DEMONSTRATING GAME ENGINE AS OF SO FAR


http://youtu.be/Q-oF2_8eDL4
Platforming Stuff, and collect bananas



http://youtu.be/AxQOaBWi1wU

Pick up and put down barrels with some glitches (Just haven't gotten to them yet they're easy to fix)

LemonWizard

And would you believe after about 3 or 4 hours of coding and preparing more graphics by focusing the sprites properly in seperate frame images, I'm not even done getting all the sprites for dixie yet?
I still have to prepare the ones of her walking while carrying a barrel, running while carrying a barrel. Jumping while carrying a barrel (it's 2-3 frames animated). And I still have to get sprites of her throwing the barrel up and foreward.
And sprites of the barrels rolling/smashing.

The reason it's running so slowly in the video is because my recording software sucks.
I'm using procaster from livestream and it sucks memory like crazy!
Anyone got anything better? >.<

kevin


I use  PBAVI (login required), Cam Studio + Virtual Dub for clipping and compressing.