PlayBASIC V1.64N2 / V164N3 (Work In Progress) Gallery

Started by kevin, April 22, 2012, 12:07:12 AM

Previous topic - Next topic

kevin

#60
  PlayBASIC V1.64N3 - Beta 2 - SpriteHitMap

     This weekend has become the sprite vs map collision challenge.  After a number of years away from those routines, they're not easiest thing in the world to pick up exactly how they work.   Although, 'works' would be an overstatement at this point.  It'll  happily detect some collisions with the map,  but apparently only when the sprite is within a certain zone of the map (top left corner).    When you leave that zone, the detection become irregular and ultimately the run time crashes.   So it seems that's a precision problem, which is leading to the crash (fetching outside of image memory).   But finding it is turning out to be more time consuming than I'd hoped.  


 It's Overflowing

       After another long exciting :) night of looking at the same sections of code over and over and over again,  it would seem the issue is indeed caused from an overflow.   It all comes down to the coordinates the scanner routine feeds to span buffer routines.   The span buffering uses 16:16 integer precision, which is pretty common in 32bit apps.   It means there's 16 bits whole part and 16 bits of fractional part.   We use 32 integers as it's quicker and more reliable than 32bit floats.   Anyway, when it goes to fetch a block, the span converter is using world space coordinate for the block, and since we've only got 16 bits of range,  this is being exceeded.   Haven't fixed it yet, but that's best evidence so far.    

         Bingo.. it's worrrrrkkkkkiiiinnnggggggg  (for now at least :))  


  Hell Eagle Mock Up

     Attached is the demo from the other day, I've commented out the sprite to map testing code, since i'm using this as my SpriteHitMap test bed.    

Sigtrygg

Hello Kevin!

Your work is great! I hope that you solve the problem with
spitehitmap. When I got the pink blocks in my map I thought
I had done something wrong. Now I know that there was an
other reason.
But the collision with the platforms works good with RectHitSpritePixels.
For me it is very useful to see how you manage the world.
I tried to render the map to an image and then tried to make a
sprite from that image. But it didn't work and I don't know if it
would bring an effect. Probably that is senseless?
In any rate thank you very much for your mock up!

Greetings

Sigtrygg

kevin

#62
  PlayBASIC V1.64N3 - Beta 3 - Download

     Here's todays version of PlayBASIC V1.64N3,   this version has the newly tweaked SpriteHitMapPixels function in it.  End up pretty much replacing the core logic of the routine,  which was worth it, given that now it's working a lot more reliably.  Still a few gremlins in the machine,  namely when the sprites out side of the map area, which seems to give a few false positives here and there.   Not too sure why, hopefully it's just the clipping.      

     Now one thing that you'll need to be aware of (if you're not already), is the pixel level comparison routines expect the two images to be in the same pixel format.  Moreover, the collision routines assume the images mask colour is 24bit.   So if you load block data that uses a mask colour of $ffff00ff (A=255,R=255,G=0.B=255) and try and run sprite to collision with it today,  you'll  get hits on the mask colour as the collision routines apply a 24bit mask ($00ffffff) to the pass colour.    So if you have such a problem then RGB mask your image with $00ffffff to clear our the alpha bits if any  (RgbMaskIMage MyBlocks,$00ffffff.  


 Old Download removed



Sigtrygg ,

QuoteI tried to render the map to an image and then tried to make a sprite from that image. But it didn't work and I don't know if it would bring an effect. Probably that is senseless?

     In terms of doing pixel level impacts on maps between sprites, that's pretty much the original approach.   We'd work out the rectangle around the sprite, then draw this section of the map to a 'temp image' then compare it to the sprite (Search for ImageHitSpritePixels).   Other methods keep the tiles as separate images and which we than make sprites out of and compare the two sprites.    Or you can use vector etc etc

     In terms of displaying maps, if you're drawing AFX maps than you'll most likely be drawing to an off screen FX surface before drawing to the frame.  Although it can be handy to cache 256*256pixel chunks of onto Video images to create high performance scrolling environments.  All comes down to how creative one is about constructing the scene.      
   


 PlayBASIC V1.64N3 - Beta 3b - Using RayHitMapPixel for Line Of Sight

      After posting beta 3, i've been back tinking around the Hell Attack mock up.    Just want to include the basic game mechanics, using maps functions rather than other approaches.    The Game originally has all the main character types stored in separate structures, I've keep what I had previously the same, but have added a more generic structure now.   Where we have a basic game character structure, from which new character types are inherited.   Much like the Action GUI mock up the other day,  the game character has unique actions.  The core functions call these actions (if they) exist, making the interface more generic.   It's a little messy in places, but fairly expansible.  

       Anyway, bellow we're looking the game world again with the canons in place.   The Canons are active and will fire at the player given the right circumstances.  Those being within a certain range and when a timer has expired.   Those are met it'll fire toward you.   The thing is, it'd not have a clear shot.  So Here I figured would be a good real life usage of RayHitMapPixels.   This function can be used for line of sight between two points, if the ray hits the world the path is obstructed, if not it's clear.    Simple enough, we I tack the code in and nothing... Turned out to be issue with the function where it wouldn't  read the Level structure properly.  It's work for the level zero but nothing else..  Annoying, but easy fix..   The result can be seen bellow.   Where each canon is firing a ray rowards the player. If it hits the map, it draws a circle at point of impact, just for something to look at.  


Sigtrygg

Great!  :D
I don't really understand how you found the overflow, but
I have to try the new funtion SpriteHitMapPixels as soon as I can.

Greetings

Sigtrygg


kevin

#64
  PlayBASIC V1.64N3 - Beta 3b

  Here's today's build, which includes more much needed corrections to the mapping library.  Which will be needed, in order to run the attached Hell Eagle Mock up correctly.


 Hell Eagle Mock

    Here's the latest version of the source code.  While the existing character types are managed individually,  I've added a generic layer to handle and remaining characters.    At this point, there's three classes of objects that fall under this category.  Canon, Canon Bullets and Explosions.     New characters just need to be named and inherited from the parent structure.  Characters have 4 or 5 set actions they might utilize.  Which are from memory CREATE, DELETE, AI, DRAW .

    So for each character type we add, we create functions in that character types name with the ACTION in the function name.  Therefore a character type "CANON"  can have CANON_CREATE()   CANON_DELETE()  , CANON_AI() functions.     When we call the generic functions, the interface will call the character action function if there's one defined.  

   Making our interface look at bit like this.  So with simple three function design, we can run pretty much run any character type in the game,  providing we stick to our simple naming convention.  

PlayBASIC Code: [Select]
Psub Init_Character(Index,Name$, Xpos, Ypos)

; set object to alive
Objects(index).Status =1
Objects(index).x =xpos
Objects(index).y =ypos
Objects(index).ClassName=Name$

F$=Name$+"_CREATE"
if FunctionExist(f$)
Objects(index).Actions.CREATE=FunctionIndex(f$)
endif


F$=Name$+"_AI"
if FunctionExist(f$)
Objects(index).Actions.AI=FunctionIndex(f$)
endif


F$=Name$+"_DRAW"
if FunctionExist(f$)
Objects(index).Actions.DRAW=FunctionIndex(f$)
endif

F$=Name$+"_DELETE"
if FunctionExist(f$)
Objects(index).Actions.Delete=FunctionIndex(f$)
endif


// --------------------------------------
// Call custom creation function
// --------------------------------------
ptr=Objects(index).Actions.CREATE
if ptr
CallFunction Ptr,INDEX
endif

EndPsub






psub Update_Characters()

For lp=0 to GetArrayElements(Objects())

if Objects(lp)

select Objects(lp).status

; -----------------------------------
case 0 ; This Object is dead, so remove it
; -----------------------------------

Delete_Character(lp)

; -----------------------------------
case 1 ; Object is alive and kicking so call it's AI function (if it has one)
; -----------------------------------
ptr=Objects(lp).Actions.AI
if ptr
CallFunction Ptr,lp
endif




endSelect

endif
next

EndpSub



;*=-----------------------------------------------------------------------------=*
;*=-----------------------------------------------------------------------------=*
; *=--------------------[ DELETE CHARACTER ] --------------------------=*
;*=-----------------------------------------------------------------------------=*
;*=-----------------------------------------------------------------------------=*


Psub Delete_Character(Index)

if Objects(Index)

Ptr=Objects(index).Actions.DELETE
if Ptr
CallFunction Ptr,INDEX
endif

Spr=Objects(index).Sprite
if GetSpriteStatus(Spr)
DeleteSprite Spr
endif


ThisAnim=Objects(index).Anim
if GetAnimStatus(ThisANim)
DeleteAnim(ThisAnim)
endif

; free this structure
Objects(Index)=Null

endif

EndPsub





 
Movie:




Source Code Attached

Sigtrygg

Hello Kevin!

Thank you for the great mock-up!
It's for me a big opportunity to learn a lot!
The structure is absolutely clear, but I have to
spend much time for understandig the whole code.
Your idea to shoot the canonbullets with rays into
the direction of eagle is very good. At the moment
the bullets shoot in angles between 280° and 80°
randomly. If bullets are allways aim the eagle, you
have to be in movement all the time and of course
you have to shoot down the canons befor you
land onto the platforms. I would like to test this
out.

Greetings

Sigtrygg
I realize that it is now very comfortable to create
and integreate new levels for the game.

kevin

#66
Sigtrygg,

Quote
The structure is absolutely clear, but I have to
spend much time for understanding the whole code.

  This is just conceptual frame work really,  rather than a blue print on how such things are done.   Generally when making programs, I tend to try and wrap up common 'operation' into functions (or psub's) to hide away the complexity.   The same goes for data, where common sets of variables get shoved into type structures.   Even, simple things like just using meaningful names, can go a long way to making programming easier.  it's might a bit of extra set up, but it pays off big time in the end.  

  The character handler in this demo is little different than one's i normally use in such demos.   It's more like the approach used in GUI's, but works just as well in game setting.  

   Related Examples

   * Abstraction Layer
   * Action GUI
   * Entity Example (Loading Game Levels)



Quote
Your idea to shoot the canonbullets with rays into
the direction of eagle is very good. At the moment
the bullets shoot in angles between 280° and 80°
randomly. If bullets are allways aim the eagle, you
have to be in movement all the time and of course
you have to shoot down the canons befor you
land onto the platforms. I would like to test this
out.

   Yeah, the canons in this demo don't behave the same as in your version.  To be honest, i'm not really trying to recreate your game, it's just been very handy to have having all the media and data sitting there, during the latest beta testing phase.   Normally i'd write a 'simple demo' when testing such things, but this is has been a lot more interesting.  

Quote
I realize that it is now very comfortable to create and integreate new levels for the game.

   That's good to hear, it's been a huge stumbling block for many over the years.  

Sigtrygg

QuoteNormally i'd write a 'simple demo' when testing such things, but this is has been a lot more interesting. 
And it is a great kind of lesson for us!
Today I analysed your code for handling the discription.txt
Once understand you can use it like a modul for future games, I think.
Or do you program every code part new, if you make a new game?
It is still hard to understand for me, how you use the types together with
the psubs, but I hope to get it soon  ;) Video on youtube is nice!!

Greetings

Sigtrygg

kevin

#68
Quote
Once understand you can use it like a modul for future games, I think. Or do you program every code part new, if you make a new game?

 This particular loader would need to be customized for different projects. Some parts could be cut'pasted across to a new project though.   If you look closely you'll notice,  for each different data section,  I've just cut'n'pasted the same slab of code and altered the Select Case statements inside.  

 i.e. these blocks

PlayBASIC Code: [Select]
;*=-----------------------------------------------------------------------------=*   
;*=-----------------------------------------------------------------------------=*
;*=-----------------------[ PARSE GAME CHARACTER SECTION ]----------------------------=*
;*=-----------------------------------------------------------------------------=*
;*=-----------------------------------------------------------------------------=*

Psub Load_World_Parse_GAME_CHARACTER_Section(Row$(),StartingIndex)

Dim Cords(10)
For lp =StartingIndex to GetArrayElements(row$())

s$=trim$(row$(lp))

if len(s$)>0
if s$="#" then exitfor

Key$,Value$=Parse_Key_And_Value(s$)

Select Upper$(Key$)
case "ADDCANON"
Count=SPlitToArray(Value$,",",Cords() )
Index = GetFreecell(Objects())
Objects(index) = New tCanon
Init_Character(Index,"CANON", Cords(0), Cords(1))

#print Key$

default
#Print "Unknown ->"+s$

EndSelect

continue
endif

next

endpsub lp




     I think with a little customization and a bit of creative thinking you could probably set up a 'fairly' generic library to use between different projects.    Although you could just use PlayUFF library.


Quote
It is still hard to understand for me, how you use the types together with the psubs, but I hope to get it soon

     Here i'm using the Types to collect related properties together.  So all the properties of the player, belong in the Players Type Structure, all the properties of the MEN belong in the men structure.     Once we've declared the Type, we can then create Variables/Arrays or Lists from that Type.  In a Typed Variable, we're got one variable (that can accessible project wide) that contains all of the fields of the Type.  

 
   
     In the mock up,  i've declared a type tPLayer to hold all the properties of the player.  It's Status, It's position, rotation angle and the sprite it'll use for it's on screen display.    Like so,

PlayBASIC Code: [Select]
   Type tPlayer
Status
Xpos#
Ypos#
Angle#
Sprite
EndType

// Set up the player state and create a sprite for it
Dim Player as tPlayer

Player = New tPlayer

Player.Status = PlayerStatus_Alive
Player.Sprite = NewSprite(0,0, GameWorld.Image.Eagle)





     Now, we could create much the same functionality using separate  integer & float variables,  like this

PlayBASIC Code: [Select]
       Global  Player_Status
Global Player_Xpos#
Global Player_Ypos#
Global Player_Angle#
Global Player_Sprite =NewSprite(0,0, GameWorld.Image.Eagle)




      This can work just as well for individual characters like the player, but can be notoriously problematic as projects get larger.  Namely we're exposing ourselves to typo's,  it generally means we have to write every drop of code in that deals with the player uniquely.. Where as we can often reduce or share the various slabs of code between all the different characters type in game, using functions/psubs.    These are just a more modern take on sub routines, they both have slightly different behaviors (See the tutorial in the Help -> Under About -> Functions&Psub ) , i generally choose to use PSUB (Protected Subroutines), since I don't use recursion all that much, if ever actually and don't mind that local variables inside the sub aren't 'cleaned' on every call. Making them quicker at runtime.

      Anyway, we're getting way off topic.   I'll post the mock up in separate thread.  
     

      The latest version of the source code can be found Hell Eagle (Map / Level Mock Up)





kevin

#69
  PlayBASIC V1.64N3 - Beta 5

     Tinkering around with a few tiny ideas tonight, one is a function to grab the vertical beam position from the video card.   The beam position is the current location (in screen scanlines) that the video card is pushing out to the monitor.  When we sync, we're either flipping the buffers in the video diver or coping to the back buffer to the front (in windows modes generally).  If we're copying a section of screen while it's being pushed we get tearing.    To avoid this we can wait for a top of frame.  However when we do this the driver sits in a busy loop, waiting for the beam to back in it's starting position.   This can make a  program chew a lot of cpu time just sitting around awaiting.  

     However, if we can read the scanline, it's possible to develop our own beam syncing.  To do this, we wait for the beam position to be beyond the bottom of our window.  Once there, we can sync without fear of tearing the moving frame. Moveover,  if the beam is positioned inside the 'window area', we can call the wait to give time back to the OS.  Making the app a little more system friendly than it otherwise would be.  Which could be handy for simple little programs.  

     The down side is not all video cards/driver support reading the beam position.   Can't do anything about that i'm afraid.   Here's a bit of an example.  

PlayBASIC Code: [Select]
 // make a black/white pattern image as backdrop
Dim Cols(1)
Cols(0)=$304050
Cols(1)=$80a080

Size =32
width=Size*8
height=Size*8
for ylp=0 to Height/Size
for xlp=0 to Width/Size
x1=xlp*size
x2=x1+size
y1=ylp*size
y2=y1+size
boxc x1,y1,x2,y2,true,cols( cell&1)
inc cell
next
next
GetImage 1,0,0,width,height



Do
cls

tileimage 1,xpos,ypos,false


Xpos=mod(xpos-2,Width)

BottomScanLineY1=GetScreenYpos()+30
BottomScanLineY1+=GetScreenHeight()
bottomScanLineY1 = ClipRange( bottomScanLineY1,0,GetDeskTopHeight())
bottomScanLineY2 = ClipRange( bottomScanLineY1+25,bottomScanLineY1,GetDeskTopHeight())

repeat
ScanLine=GetVBL()
Dy=BottomScanLineY1-ScanLine
if dy>0
Ticks=Cliprange(Dy/200,0,10)
if Ticks
Wait Ticks
endif
endif
until (ScanLine=>BottomScanLineY1) and (ScanLine=<(BottomScanLineY2))
Sync
loop






Recasting Type Identifier

  The parameter parser will now auto recast type identifiers when passed into User defined functions (or psubs).     Which will be helpful in programs like the Abstraction Layer

PlayBASIC Code: [Select]
   Type Dude
Wobbley
endtype

Type Vertex
x#,y#,z#
EndType

Yeah Vertex
Test Vertex

Sync
WaitKey


Function Yeah(ThisTypeIndex)
print ThisTypeIndex
EndFunction


Psub Test(ThisTypeIndex)
print ThisTypeIndex
EndPsub


     



CallFunction Supports Pointer Parameters

   Added some pointer passing support to the CallFunction operation in the run time.   Being able to pass pointers in will be very helpful building function sets that are more generic object based.   Still can't return results, unfortunately that's due to byproduct of how the runtime works.    

PlayBASIC Code: [Select]
   Type Dude
Wobbley
endtype

Type Vertex
x#,y#,z#
EndType

Dim a(0) as Vertex
a(0).x=100
a(0).y=200
a(0).z=300

Dim Cool as Vertex Pointer
Cool=New Vertex

Cool.x=111
Cool.y=112
Cool.z=113



callfunction "Test2",A(0).Vertex
callfunction "Test2",Cool


Sync
WaitKey


Function Test1(me as Vertex)
if Int(me)
print me.x
print me.y
print me.z
else
print "Failed"
endif
EndFunction


Psub Test2(me as Vertex Pointer)
if Int(Me)
print me.x
print me.y
print me.z
else
print "Failed"
endif
EndPsub





  CallFunction includes some support for Passing Arrays()

    It's about bed time for me, but not without one final update.  Have continued messing around with the CallFunction parameter support and have got it handled passing Arrays() into Psubs ( no functions as yet)..   But it does indeed work,  so i'm  pretty happy with that.  


PlayBASIC Code: [Select]
   Dim Temp(5)

callFunction "Test4",Temp()
callFunction "Test4",Temp()

Sync
WaitKey



Function Test3(Stuff())
if GetArrayStatus(Stuff())
for lp =0 to GetArrayElements(Stuff())
STuff(lp)++
print Stuff(lp)
next
else
print "Failed"
endif
EndFunction


Psub Test4(Stuff())

if GetArrayStatus(Stuff())
for lp =0 to GetArrayElements(Stuff())
STuff(lp)++
print Stuff(lp)
next
else
print "Failed"
endif
EndPsub









   




kevin


PlayBASIC V1.64N3 - Beta 5 - Download



  Download   Download PlayBASIC V1.64N3 - Beta5 (login required)

kevin

#71
  So am I to assume, every-bodies running the Beta5 without any issues then ?  Would like to wrap this all up pretty quickly that's all



OldNESJunkie

Sorry Kevin, personally haven't had the time to test this beta out, had too much going on with family "things", I'll d/l it tonight, try it out with my project, let you know if anything crops up ???

kevin

#73
 PlayBASIC V1.64N3 - Beta 6

      Back hacking away at the update this morning, noticed a problem with captured text a while ago and completely forgot  about until running into again.    So tracking down the cause of that has been focus this session.  Turned out the captured string length parameter was being padded from some completely unknown reason.  Can't help feeling a little nervous about such changes now, since there may well be some situation where that was indeed required...  Yeah.. what fun :)

PlayBASIC Code: [Select]
   loadfont "arial",1,32,0
loadfont "arial",2,32,0,8

A$="Hello World"

Cam=NewCamera()

Do
setcursor 0,0
CaptureToScene
ClsScene
setfont 1
print a$
text 200,100,a$
print str$(counter)
print str$(counter2)


setfont 2
print a$
text 200,300,a$
print str$(counter)
print str$(counter2)

counter++
drawcamera 1
Sync
loop






kevin


Another Quick Documentation Pass

        Tonight's little chore is to give the Map collision commands another pass in the documentation, starting with RayHitMapPixels function.   Taking longer than I'd expected, but so do all things documentation.    Mostly been adding some stuff on possible uses, that sorta thing.     There's a few commands missing from the doc's for whatever reason, so those will have to added also.  Shouldn't be too much of a drama, just a big drain on the creative process.. :)

        The current time line for building the V1.64N3 upgrade is probably Tuesday (my time).