Author Topic: Axe Tilemapping and Optimization  (Read 3821 times)

0 Members and 1 Guest are viewing this topic.

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Axe Tilemapping and Optimization
« on: September 03, 2011, 01:19:47 pm »
I started a project for the Axe Progamming Contest but I soon quit it because of tilemapping, because I didnt't find a way of not having to redraw all the screen all the time, which made my game run quite slow.

Here's the full code (without tilemapping, I use graphing commands to design the map):

Code: [Select]
.A
#Icon(FFFF8001BC3DA5E5A525BD2581E59C3D95C19D7981C9BE89A289BEF98001FFFF)
[E0E0808000000000]->Pic1
ClrDraw^^r
Fix 5
1280->X
10240->Y
0->A->B
24->C
20->E
Repeat getKey(15)
  .CHECK IF USER IS TOUCHING FLAG
  If (X/256-C+4<=8) and (Y/256-E+4<=8)
    Return
  End

  .CHECK IF ENEMY ON THE LEFT
  0->J
  For(I,0,3)
    If (pxl-Test(X/256-1,Y/256+I)^^r)
      1->J
    End
  End

  .CHECK IF ENEMY ON THE RIGHT
  0->K
  For(I,0,3)
    If (pxl-Test(X/256+4,Y/256+I)^^r)
      1->K
    End
  End

  .CHECK IF ENEMY ON TOP
  0->M
  For(I,0,3)
    If (pxl-Test(X/256+I,Y/256-1)^^r)
      1->M
    End
  End

  .CHECK IF ENEMY BELOW THE PLAYER
  0->N
  For(I,0,3)
    If (pxl-Test(X/256+I,Y/256+4)^^r)
      1->N
    End
  End

  .IF AN ENEMY IS TOUCHING THE PLAYER
  If (N) or (M) or (J) or (K)
    Return
  End

  .CHECK IF WALL ON THE LEFT
  0->L
  For(I,0,3)
    If (pxl-Test(X/256-1,Y/256+I))
      1->L
    End
  End

  .CHECK IF WALL ON THE RIGHT
  0->R
  For(I,0,3)
    If (pxl-Test(X/256+4,Y/256+I))
      1->R
    End
  End

  .IF ANYTHING ON THE RIGHT OR ON THE LEFT, STOP
  If L or (R)
    0->A
  End

  .CHECK IF ANYTHING UNDER THE PLAYER
  0->D
  For(I,0,3)
    If (pxl-Test(X/256+I,Y/256+4))
      1->D
    End
  End

  .GRAVITY
  B+5->B
  For(I,0,3)
    If pxl-Test(X/256+I,Y/256-1+(B>>0*5))
      0->B
    End
  End

  .GO LEFT
  If getKey(2) and (A>>~255) and (L=0)
    A-32->A
  End

  .GO RIGHT
  If getKey(3) and (A<<256) and (R=0)
    A+32->A
  End

  .JUMP WHEN USER PRESSES UP
  If getKey(4) and (D)
    ~256->B
  End

  .WALL JUMP ON THE LEFT
  If (R) and (D=0) and (getKey(2)) and (getKey(4))
    ~100->B
    A-40->A
  End

  .WALL JUMP ON THE RIGHT
  If (L) and (D=0) and (getKey(3)) and (getKey(4))
    ~100->B
    A+40->A
  End

  .LIMIT SPEED AT 1 PIXEL
  If (B>>256)
    256->B
  End

  .FRICTION
  If A-1=>=>0
    A-2->A
  End

  .FRICTION
  If A//32768
    A+2->A
  End

  .UPDATE POSITIONS
  X+A->X
  Y+B->Y

  .DRAW THE MAP
  Rect(0,0,96,64)
  RectI(4,4,88,56)
  Rect(20,24,12,4)

  .DRAW THE PLAYER
  Rect(X/256,Y/256,4,4)

  .DRAW THE FLAG
  Pt-On(C,E,Pic1)

  DispGraph^^r
End

Basically, enemies are whatever is gray on the screen, so if the player touches something gray, the game stops.

There are two things I need help with:
  • Implementing tilemapping to draw levels in a way that doesn't make the game too slow
  • Make it so that the user doesn't go through walls when jumping

Here's a screenshot of the second:



I made this code a few weeks ago, so I don't exactly remember how everything works, but from what I understand, I'm never checking if there's anything above the player, am I?

I know my help request sounds a bit vague, but it's hard to make it more specific.

Ashbad

  • Guest
Re: Axe Tilemapping and Optimization
« Reply #1 on: September 03, 2011, 02:15:43 pm »
Why not draw the tilemap once, save the screen to a buffer, and recall that buffer at the beginning of each render loop?  That's what I do whenever possible, and why TaNF/UCTI both ran at well over 45 FPS.

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: Axe Tilemapping and Optimization
« Reply #2 on: September 03, 2011, 04:14:35 pm »
Why not draw the tilemap once, save the screen to a buffer, and recall that buffer at the beginning of each render loop?  That's what I do whenever possible, and why TaNF/UCTI both ran at well over 45 FPS.

Which buffer would I save it to, though? And how to recall itl, do I use RecallPic? I am not familiar with those concepts, so thanks Ashbad :)

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: Axe Tilemapping and Optimization
« Reply #3 on: September 03, 2011, 04:33:20 pm »
As long as you are not using smoothscrolling nor greyscale, you can use StorePic to store your front buffer into the backbuffer (L3) and then RecalPic to recall it back into your front buffer (L6).  If you are using smoothscrolling, it can be a little more tricky, but I believe there are some fast smoothscrolling tilemappers out there. 

If you are using greyscale and absolutely need the speed, you can allocate an extra 768 bytes from an appvar or your program, and use that coupled with L1 for backups of both the front and main buffer, just remember to relocate your variables to somewhere other than L1, that way you can use L1's full 768 bytes

Offline willrandship

  • Omnimagus of the Multi-Base.
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2953
  • Rating: +98/-13
  • Insert sugar to begin programming subroutine.
    • View Profile
Re: Axe Tilemapping and Optimization
« Reply #4 on: September 03, 2011, 04:35:20 pm »
Thanks to the awesome arbitrary buffer support in 1.0.3, you can use any buffer you wish! If you're not using the backbuffer, though, you might as well just use it.

You can make a buffer in RAM by using the "zeros(768)->Varname" command, and then use the regular drawing commands, usually followed by (Varname), but you should probably just look up those commands to make sure I didn't screw anything up.

Also, the Front buffer and backbuffer already have pointers assigned to them: L3 (back) and L6 (Front).

Edit: ninja, of course :P
« Last Edit: September 03, 2011, 04:37:08 pm by willrandship »

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: Axe Tilemapping and Optimization
« Reply #5 on: September 04, 2011, 05:52:49 am »
Code: [Select]
.DRAW MAP USING TILEMAPPING CODE HERE
StorePic

Repeat getKey(15)

RecallPic
DispGraph^^r
End

Something like that? The problem is the grayscale, and Builderboy told me how to do it (use an Appvar to get 768 extra bytes), but I'm thinking that's too complicated, so I'll have to think about it.

Ashbad

  • Guest
Re: Axe Tilemapping and Optimization
« Reply #6 on: September 04, 2011, 11:42:55 am »
Well, in TaNF I did it except with a size==768*4, so it's rather necessary at many times.  It's not complicated, you can really just do it with something like:

Code: [Select]
GetCalc("appvTEMP01",2*768) -> B
TilemapDrawingRoutine()
Copy(L6,B,768):Copy(L3,B+768,768)

...
code
...

Lbl REDR .Redraw Routine
  Copy(B,L6,768):Copy(B+768,L3,768)
Return

Just make sure you only edit the allocated buffer when you enter a new room or the room's structure changes, and you free the allocation before the final return from the program.
« Last Edit: September 04, 2011, 11:43:15 am by Ashbad »