This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Show posts MenuQuoteWe need a new version ?!
Quote- collision detection could have a smaller radius/square then current. It feels strange when the player stops on an invisible wall, particularly the borders of platforms, where the tile is not quite square.
- when jumping on a no-space-to-jump situation, the jump sound gets repeated while no action goes on.
// ------------------------------------------------------------- //
// --- FNCREATEGHOSTS ---
// ------------------------------------------------------------- //
FUNCTION fnCreateGhosts:
LOCAL lcnt
// randomize ghost quantity
NumGhosts = RND(10)
REDIM tGhost[NumGhosts]
// initialize ghosts
FOR lcnt = 0 TO NumGhosts - 1
tGhost[lcnt].x = RND(639)
tGhost[lcnt].y = RND(479)
tGhost[lcnt].HP = 5
tGhost[lcnt].attack_cnt = 1
tGhost[lcnt].ani = RND(1)
tGhost[lcnt].ani_cnt = RND(14) + 1
tGhost[lcnt].shot_x = 10000
tGhost[lcnt].shot_y = 10000
tGhost[lcnt].shot_cnt = RND(89) + 1
NEXT
ENDFUNCTION // FNCREATEGHOSTS
// reset to main directory
SETCURRENTDIR(MainDir$)
// set number of ghosts to 0
NumGhosts = 0
// create generic map if file doesn´t exists
ELSE
// create ghosts
fnCreateGhosts()
// clear shots
FOR lx = 0 TO tChar.shotquantity -1
tShot[lx].angle = -1
NEXT
// counter for death animation
GLOBAL DeathCnt
// heal hitpoints
INC tChar.HP, tChar.healrate
IF tChar.HP > tChar.maxHP; tChar.HP = tChar.maxHP; ENDIF
// attack animation
IF mbl; INC tChar.ani, 20; ENDIF
// compute character / death animation
IF tChar.HP > 0 // alive
fnComputeChar()
DRAWANIM 2, tChar.ani, tChar.x, tChar.y
ELSE // death
DRAWANIM 2, 40 + DeathCnt, tChar.x, tChar.y
INC DeathCnt, 0.3
IF DeathCnt > 11; DeathCnt = 11; ENDIF
PRINT "ENTER", 285, 233
IF KEY(28) // [ENTER]
tChar.HP = 1
SectorX = 100
SectorY = 100
tChar.x = 307; tChar.y = 232
tChar.gems = 0
DeathCnt = 0
fnLoadMap()
ENDIF
ENDIF
// display health bar
IF tChar.HP > 0
ALPHAMODE 0.5
DRAWRECT 623, 471, 8, -tChar.HP, RGB(255, 0, 0)
ALPHAMODE 0
ENDIF
// ------------------------------------------------------------- //
// --- FNATTRIBUTES ---
// ------------------------------------------------------------- //
FUNCTION fnAttributes:
LOCAL lIndex, lDelay = 7
// grab screen
GRABSPRITE 0, 0, 0, 640, 480
WHILE KEY(46) // [C]
GOSUB subReadMouse
// draw backgound
ALPHAMODE 0.5
DRAWSPRITE 0, 0, 0
ALPHAMODE 0
// compute index / draw rectangle
lIndex = INTEGER(my) / 32
IF lIndex > 1 AND lIndex < 8
ALPHAMODE 0.5
DRAWRECT 0, lIndex * 32, 640, 32, RGB(255, 0, 0)
ALPHAMODE 0
ENDIF
PRINT "XP: " + tChar.XP, 16, 16
// speed
PRINT "Geschwindigkeit = " + tChar.speed, 16, 64
PRINT "Kosten:" + ( tChar.speed * 10 + 100 ) + " / +0.1", 16, 80
IF mbl AND lIndex = 2 AND lDelay = 0 AND ( tChar.speed * 10 + 100 ) <= tChar.XP
DEC tChar.XP, ( tChar.speed * 10 + 100 )
INC tChar.speed, 0.1
lDelay = 7
ENDIF
// max HP
PRINT "max HP = " + tChar.maxHP, 16, 96
PRINT "Kosten:" + ( INTEGER(tChar.maxHP / 10) + 10 ) + " / +1", 16, 112
IF mbl AND lIndex = 3 AND lDelay = 0 AND ( INTEGER(tChar.maxHP / 10) + 10 ) <= tChar.XP
DEC tChar.XP, ( INTEGER(tChar.maxHP / 10) + 10 )
INC tChar.maxHP, 1
tChar.healrate = tChar.maxHP / 10000
lDelay = 7
ENDIF
// shotpower
PRINT "Magie: Schaden = " + tChar.shotpower, 16, 128
PRINT "Kosten:" + ( tChar.shotpower * 100 + 100) + " / +1", 16, 144
IF mbl AND lIndex = 4 AND lDelay = 0 AND ( tChar.shotpower * 100 + 100) <= tChar.XP
DEC tChar.XP, ( tChar.shotpower * 100 + 100)
INC tChar.shotpower, 1
lDelay = 7
ENDIF
// interval
PRINT "Magie: Intervall = " + tChar.shotinterval, 16, 160
PRINT "Kosten:" + ( (15 - tChar.shotinterval) * 100 + 100 ) + " / -1", 16, 176
IF mbl AND lIndex = 5 AND lDelay = 0 AND ( (15 - tChar.shotinterval) * 100 + 100 ) <= tChar.XP
DEC tChar.XP, ( (15 - tChar.shotinterval) * 100 + 100 )
DEC tChar.shotinterval, 1
lDelay = 7
ENDIF
// shotspeed
PRINT "Magie: Geschwindigkeit = " + tChar.shotspeed, 16, 192
PRINT "Kosten:" + ( tChar.shotspeed * 10 + 100 ) + " / +0.5", 16, 208
IF mbl AND lIndex = 6 AND lDelay = 0 AND ( tChar.shotspeed * 10 + 100 ) <= tChar.XP
DEC tChar.XP, ( tChar.shotspeed * 10 + 100 )
INC tChar.shotspeed, 0.5
lDelay = 7
ENDIF
// shotquantity
PRINT "Magie: Anzahl = " + tChar.shotquantity, 16, 224
PRINT "Kosten:" + ( tChar.shotquantity * 10 + 100 ) + " / +1", 16, 240
IF mbl AND lIndex = 7 AND lDelay = 0 AND ( tChar.shotquantity * 10 + 100 ) <= tChar.XP
DEC tChar.XP, ( tChar.shotquantity * 10 + 100 )
INC tChar.shotquantity, 1
REDIM tShot[tChar.shotquantity]
lDelay = 7
ENDIF
DEC lDelay, 1
IF lDelay < 0; lDelay = 0; ENDIF
// draw mouse pointer
DRAWSPRITE 1, mx-15, my-15
SHOWSCREEN
WEND
ALPHAMODE 0.5
DRAWSPRITE 0, 0, 0
ALPHAMODE 0
// delete sprite
LOADSPRITE "", 0
ENDFUNCTION // FNATTRIBUTES
// call attributes screen
IF KEY(46) // [C]
fnAttributes()
ENDIF
shotpower // damage of shot
shotinterval // interval between shots in frames
interval_cnt // interval counter
shotspeed // speed in pixel per frame of shot
shotquantity // max number of shots
shotindex // current index of TTshot
gems // quantity of gems
maxHP // max hitpoints
HP // current hitpoints
healrate // healing rate per frame
XP // experience points
// type for shots
TYPE TTshot
x
y
angle
ENDTYPE
GLOBAL tShot[] AS TTshot
// type for ghosts
TYPE TTghost
x
y
HP // hitpoints
attack_mode // 0 = hunt; 1 = random movement
attack_cnt // time to compute new attack mode
ani // current animation frame
ani_cnt // time to change animation frame
angle // movement angle
shot_x // x coord of shot
shot_y // y coord of shot
shot_cnt // duration counter of shot
shot_angle // movement angle of shot
ENDTYPE
GLOBAL tGhost[] AS TTghost
tChar.shotpower = 1 // damage of shot
tChar.shotinterval = 15 // interval between shots in frames
tChar.shotspeed = 4 // speed in pixel per frame of shot
tChar.shotquantity = 3 // maximal number of shots
tChar.HP = 100 // current hitpoints
tChar.maxHP = 100 // maximal hitpoints
tChar.healrate = 0.01 // initial healing rate / incrementor per frame
// initialize shots
REDIM tShot[tChar.shotquantity]
FOR lcnt = 0 TO tChar.shotquantity - 1
tShot[lcnt].angle = -1
NEXT
// load shot
LOADSPRITE "Shot.png", 5
// load ghost anim
LOADANIM "Ghost.png", 6, 28, 32
// load gem GFX
LOADSPRITE "Gem.png", 7
// load ghost projectile
LOADSPRITE "GhostShot.png", 8
// ------------------------------------------------------------- //
// --- FNCOMPUTESHOT ---
// ------------------------------------------------------------- //
FUNCTION fnComputeShot:
LOCAL lcnt
STATIC lInterval
// create and initialize shot
IF mbl AND tChar.interval_cnt = 0
INC tChar.shotindex, 1
IF tChar.shotindex = tChar.shotquantity
tChar.shotindex = 0
ENDIF
// initialize coordinates
tShot[tChar.shotindex].x = tChar.x - 3
tShot[tChar.shotindex].y = tChar.y - 8
// store angle between shot and mouse cursor
tShot[tChar.shotindex].angle = fnGetAngle(tShot[tChar.shotindex].x+16, tShot[tChar.shotindex].y+16, mx, my)
// set interval
tChar.interval_cnt = tChar.shotinterval
ENDIF
// move and draw shot
ALPHAMODE 0.75
FOR lcnt = 0 TO tChar.shotquantity - 1
// compute shot
IF tShot[lcnt].angle <> -1 // move shot if it´s existant
tShot[lcnt].x = fnMoveX(tShot[lcnt].angle, tShot[lcnt].x, tChar.shotspeed)
tShot[lcnt].y = fnMoveY(tShot[lcnt].angle, tShot[lcnt].y, tChar.shotspeed)
// draw shot
DRAWSPRITE 5, tShot[lcnt].x, tShot[lcnt].y
// delete shot when it leaves the screen
IF tShot[lcnt].x < - 16 OR tShot[lcnt].x > 656 OR tShot[lcnt].y < -16 OR tShot[lcnt].y > 496
tShot[lcnt].angle = -1
// delete shot when it collides with an obstacle
ELSEIF fnObstacleCollision(tShot[lcnt].x, tShot[lcnt].y, 5, 0)
tShot[lcnt].angle = -1
ENDIF
ENDIF
NEXT
ALPHAMODE 0
// decrease interval
DEC tChar.interval_cnt, 1; IF tChar.interval_cnt < 0; tChar.interval_cnt = 0; ENDIF
ENDFUNCTION // FNCOMPUTESHOT
// number of ghost units
GLOBAL NumGhosts
LOCAL lcnt, lcnt2, lDistance, lAngle
IF NumGhosts <> 0 // if any ghosts exist
FOR lcnt = 0 TO NumGhosts - 1
IF tGhost[lcnt].HP > 0 // alive
// compute attack mode
IF tGhost[lcnt].attack_cnt = 0
// compute distance / decide attack mode
lDistance = fnGetDistance(tGhost[lcnt].x, tGhost[lcnt].y, tChar.x + 13, tChar.y + 8)
IF lDistance > 250
tGhost[lcnt].attack_mode = 0 // hunt
ELSE
tGhost[lcnt].attack_mode = 1 // random
tGhost[lcnt].angle = fnGetAngle(tGhost[lcnt].x, tGhost[lcnt].y, RND(639), RND(479))
ENDIF
// set attack counter
tGhost[lcnt].attack_cnt = RND(15) + 15
ENDIF
// decrease attack counter
DEC tGhost[lcnt].attack_cnt, 1
// compute animation
DEC tGhost[lcnt].ani_cnt, 1
IF tGhost[lcnt].ani_cnt = 0
tGhost[lcnt].ani = 1 - tGhost[lcnt].ani
tGhost[lcnt].ani_cnt = 15
ENDIF
// move ghost
IF tGhost[lcnt].attack_mode = 0 // hunt
lAngle = fnGetAngle(tGhost[lcnt].x, tGhost[lcnt].y, tChar.x + 13, tChar.y + 8)
tGhost[lcnt].x = fnMoveX(lAngle, tGhost[lcnt].x, 3)
tGhost[lcnt].y = fnMoveY(lAngle, tGhost[lcnt].y, 3)
ELSE // random
tGhost[lcnt].x = fnMoveX(tGhost[lcnt].angle, tGhost[lcnt].x, 3)
tGhost[lcnt].y = fnMoveY(tGhost[lcnt].angle, tGhost[lcnt].y, 3)
ENDIF
// compute ghost shot
DEC tGhost[lcnt].shot_cnt, 1
// initialize shot
IF tGhost[lcnt].shot_cnt = 0
tGhost[lcnt].shot_x = tGhost[lcnt].x
tGhost[lcnt].shot_y = tGhost[lcnt].y
tGhost[lcnt].shot_angle = fnGetAngle(tGhost[lcnt].x, tGhost[lcnt].y, tChar.x + 13, tChar.y + 8)
tGhost[lcnt].shot_cnt = 90
ENDIF
// move shot
tGhost[lcnt].shot_x = fnMoveX(tGhost[lcnt].shot_angle, tGhost[lcnt].shot_x, 5)
tGhost[lcnt].shot_y = fnMoveY(tGhost[lcnt].shot_angle, tGhost[lcnt].shot_y, 5)
// draw shot
ALPHAMODE (tGhost[lcnt].shot_cnt + 10) / 100
DRAWSPRITE 8, tGhost[lcnt].shot_x - 16, tGhost[lcnt].shot_y - 16
// check collision: ghost shot -> player
IF ANIMCOLL(8, 0, tGhost[lcnt].shot_x - 16, tGhost[lcnt].shot_y - 16, 2, tChar.ani, tChar.x, tChar.y)
DEC tChar.HP, tGhost[lcnt].shot_cnt / 10 // decrease HP
tGhost[lcnt].shot_x = 10000
tGhost[lcnt].shot_y = 10000
ENDIF
// check collision: ghost -> player shot
FOR lcnt2 = 0 TO tChar.shotquantity - 1
IF tShot[lcnt2].angle <> -1 // if shot is active
IF ANIMCOLL(6, 0, tGhost[lcnt].x - 14, tGhost[lcnt].y - 16, 5, 0, tShot[lcnt2].x, tShot[lcnt2].y)
DEC tGhost[lcnt].HP, tChar.shotpower // decrease ghost HP by shotpower
tShot[lcnt2].angle = -1 // "delete" shot
// causes sprite to "blink" when hit
DRAWANIM 6, tGhost[lcnt].ani, tGhost[lcnt].x - 14, tGhost[lcnt].y - 16
ENDIF
ENDIF
NEXT
// increase XP if ghost is dead
IF tGhost[lcnt].HP <= 0
INC tChar.XP, 10
tGhost[lcnt].HP = 0
ENDIF
// check collision: ghost -> player
IF ANIMCOLL(6, 0, tGhost[lcnt].x - 14, tGhost[lcnt].y - 16, 2, tChar.ani, tChar.x, tChar.y)
DEC tChar.HP, 1
ENDIF
// draw ghost
ALPHAMODE -0.5
DRAWANIM 6, tGhost[lcnt].ani, tGhost[lcnt].x - 14, tGhost[lcnt].y - 16
ELSEIF tGhost[lcnt].HP = 0 // gem
// draw gem
ALPHAMODE 1
DRAWSPRITE 7, tGhost[lcnt].x - 16, tGhost[lcnt].y - 16
// get gem
IF ANIMCOLL(7, 0, tGhost[lcnt].x - 16, tGhost[lcnt].y - 16, 2, tChar.ani, tChar.x, tChar.y)
tGhost[lcnt].HP = -1
INC tChar.gems, 1
ENDIF
ENDIF
NEXT
ALPHAMODE 0
ENDIF
// change to editor mode
IF KEY(15) AND KeyDelay = 0 // [TAB]
fnEditor()
ENDIF
// ------------------------------------------------------------- //
// --- FNSELECTTILE ---
// .............................................................
// tile selection mode
// ------------------------------------------------------------- //
FUNCTION fnSelectTile:
LOCAL lx, ly, lcnt, lTileIndex
WHILE KEY(57) // [SPACE]
// read mouse state
GOSUB subReadMouse
// draw background color
DRAWRECT 0, 0, 640, 480, RGB(255, 0, 128)
// reset counter
lcnt = 0
// display tiles
FOR ly = 0 TO 29
FOR lx = 0 TO 39
DRAWANIM 3, lcnt, lx * 16, ly * 16
INC lcnt, 1
IF lcnt = cNUM_TILES; BREAK; ENDIF
NEXT
IF lcnt = cNUM_TILES; BREAK; ENDIF
NEXT
// draw selector
DRAWSPRITE 4, INTEGER(mx) / 16 * 16, INTEGER(my) / 16 * 16
// tile index
lTileIndex = (INTEGER(my) / 16 * 40) + mx / 16
// select tile
IF mbl
eTile = lTileIndex
IF eTile > cNUM_TILES; eTile = 0; ENDIF
ENDIF
// fill map with chosen tile
IF mbr
FOR ly = 0 TO 29
FOR lx = 0 TO 39
tMap[lx][ly].ground[0] = lTileIndex
NEXT
NEXT
ENDIF
// draw mouse pointer
DRAWSPRITE 1, mx-15, my-15
SHOWSCREEN
WEND
ENDFUNCTION // FNSELECTTILE
// call selection mode
IF KEY(57) // [SPACE]
fnSelectTile()
ENDIF
// ------------------------------------------------------------- //
// --- FNRND ---
// ------------------------------------------------------------- //
FUNCTION fnRnd:
LOCAL lx, ly
FOR ly = 0 TO 29
FOR lx = 0 TO 39
SELECT tMap[lx][ly].ground[0]
CASE 2 TO 5 // grass
tMap[lx][ly].ground[0] = RND(3) + 2
IF RND(24) = 0
tMap[lx][ly].ground[1] = RND(19) + 10
IF tMap[lx][ly].ground[1] = 22
tMap[lx][ly].ground[1] = 0
ENDIF
ELSE
tMap[lx][ly].ground[1] = 0
ENDIF
IF RND(32) = 0 AND lx > 0 AND lx < 39 AND ly > 0 AND ly < 29
tMap[lx][ly].obstacle = RND(4) + 67
ELSE
tMap[lx][ly].obstacle = 0
ENDIF
CASE 6 TO 8 // bricks
tMap[lx][ly].ground[0] = RND(2) + 6
ENDSELECT
NEXT
NEXT
ENDFUNCTION // FNRND
// random tiles
IF KEY(156) // [ZB ENTER]
fnRnd()
ENDIF
// ------------------------------------------------------------- //
// --- FNCLEARMAP ---
// ------------------------------------------------------------- //
FUNCTION fnClearMap:
LOCAL lx, ly
FOR ly = 0 TO 29
FOR lx = 0 TO 39
tMap[lx][ly].ground[0] = 0
tMap[lx][ly].ground[1] = 0
tMap[lx][ly].obstacle = 0
tMap[lx][ly].overlay = 0
NEXT
NEXT
ENDFUNCTION // FNCLEARMAP
Füge folgenden Code in "fnEditor" ein:
IF KEY(74) // [ZB-]
fnClearMap()
ENDIF
// global coordinates
GLOBAL SectorX = 100, SectorY = 100
// ------------------------------------------------------------- //
// --- FNSAVEMAP ---
// ------------------------------------------------------------- //
FUNCTION fnSaveMap:
LOCAL lx, ly
// open map directory
SETCURRENTDIR(MainDir$ + "/Maps")
OPENFILE(1, SectorX + "_" + SectorY + ".map", FALSE)
// save map data
FOR ly = 0 TO 29
FOR lx = 0 TO 39
WRITELINE 1, tMap[lx][ly].ground[0]
WRITELINE 1, tMap[lx][ly].ground[1]
WRITELINE 1, tMap[lx][ly].obstacle
WRITELINE 1, tMap[lx][ly].overlay
NEXT
NEXT
CLOSEFILE 1
// reset to main directory
SETCURRENTDIR(MainDir$)
ENDFUNCTION // FNSAVEMAP
// ------------------------------------------------------------- //
// --- FNLOADMAP ---
// ------------------------------------------------------------- //
FUNCTION fnLoadMap:
LOCAL lx, ly
// open map directory
SETCURRENTDIR(MainDir$ + "/Maps")
// load map when file exists
IF DOESFILEEXIST(SectorX + "_" + SectorY + ".map")
OPENFILE(1, SectorX + "_" + SectorY + ".map", TRUE)
// read map data
FOR ly = 0 TO 29
FOR lx = 0 TO 39
READLINE 1, tMap[lx][ly].ground[0]
READLINE 1, tMap[lx][ly].ground[1]
READLINE 1, tMap[lx][ly].obstacle
READLINE 1, tMap[lx][ly].overlay
NEXT
NEXT
CLOSEFILE 1
// reset to main directory
SETCURRENTDIR(MainDir$)
// create generic map if file doesn´t exists
ELSE
// initialize map
FOR ly = 0 TO 29
FOR lx = 0 TO 39
tMap[lx][ly].ground[0] = 2
tMap[lx][ly].ground[1] = 0
tMap[lx][ly].obstacle = 0
tMap[lx][ly].overlay = 0
NEXT
NEXT
// randomize tiles
SEEDRND SectorX + SectorY
fnRnd()
SEEDRND GETTIMERALL()
ENDIF
// reset to main directory
SETCURRENTDIR(MainDir$)
ENDFUNCTION // FNLOADMAP
// navigate trough sectors
IF KEY(200) AND KeyDelay = 0 AND SectorY > 0 // [ARROW UP]
DEC SectorY, 1; KeyDelay = 7; fnLoadMap()
ENDIF
IF KEY(208) AND KeyDelay = 0 // [ARROW DOWN]
INC SectorY, 1; KeyDelay = 7; fnLoadMap()
ENDIF
IF KEY(203) AND KeyDelay = 0 AND SectorX > 0 // [ARROW LEFT]
DEC SectorX, 1; KeyDelay = 7; fnLoadMap()
ENDIF
IF KEY(205) AND KeyDelay = 0 // [ARROW RIGHT]
INC SectorX, 1; KeyDelay = 7; fnLoadMap()
ENDIF
// save map
IF KEY(63) // [F5]
fnSaveMap()
ENDIF
// load map
SETCURRENTDIR(MainDir$ + "/Maps")
fnLoadMap()
// ------------------------------------------------------------- //
// --- FNDRAWOVERLAY ---
// ------------------------------------------------------------- //
FUNCTION fnDrawOverlay:
LOCAL lx, ly
FOR ly = 0 TO 29
FOR lx = 0 TO 39
// draw overlay tiles
DRAWANIM 3, tMap[lx][ly].overlay, lx * 16, ly * 16
NEXT
NEXT
ENDFUNCTION // FNDRAWOVERLAY
tileX // global x coordinate
tileY // global y coordinate
// ------------------------------------------------------------- //
// --- FNOVERLAYCOLLISION ---
// ------------------------------------------------------------- //
FUNCTION fnOverlayCollision:
LOCAL lx, ly, lx1, ly1, lx2, ly2, lColl
// set scanning coordinates
lx1 = tChar.tileX - 1
ly1 = tChar.tileY - 1
lx2 = tChar.tileX + 1
ly2 = tChar.tileY + 1
// correct scanning coordinates
IF lx1 < 0; lx1 = 0; ENDIF
IF ly1 < 0; ly1 = 0; ENDIF
IF lx2 > 39; lx2 = 39; ENDIF
IF ly2 > 29; ly2 = 29; ENDIF
// check for collision
FOR ly = ly1 TO ly2
FOR lx = lx1 TO lx2
IF ANIMCOLL(2, tChar.ani, tChar.x, tChar.y, 3, tMap[lx][ly].overlay, lx * 16, ly * 16)
lColl = TRUE
ENDIF
NEXT
NEXT
RETURN lColl
ENDFUNCTION // FNOVERLAYCOLLISION
// ------------------------------------------------------------- //
// --- FNDRAWOVERLAY ---
// ------------------------------------------------------------- //
FUNCTION fnDrawOverlay:
LOCAL lx, ly
IF fnOverlayCollision() = FALSE
FOR ly = 0 TO 29
FOR lx = 0 TO 39
// draw overlay tiles
DRAWANIM 3, tMap[lx][ly].overlay, lx * 16, ly * 16
NEXT
NEXT
ENDIF
ENDFUNCTION // FNDRAWOVERLAY
// ------------------------------------------------------------- //
// --- FNOBSTACLECOLLISION ---
// ------------------------------------------------------------- //
FUNCTION fnObstacleCollision: lx, ly, lid, ltile
LOCAL lx1, ly1, lx2, ly2, lx3, ly3, lColl
// set scanning coordinates
lx1 = INTEGER( lx / 16) - 1
ly1 = INTEGER( ly / 16) - 1
lx2 = INTEGER( lx / 16) + 1
ly2 = INTEGER( ly / 16) + 1
// correct scanning coordinates
IF lx1 < 0; lx1 = 0; ENDIF
IF ly1 < 0; ly1 = 0; ENDIF
IF lx2 > 39; lx2 = 39; ENDIF
IF ly2 > 29; ly2 = 29; ENDIF
// check for collision
FOR ly3 = ly1 TO ly2
FOR lx3 = lx1 TO lx2
IF ANIMCOLL(lid, ltile, lx, ly, 3, tMap[lx3][ly3].obstacle, lx3 * 16, ly3 * 16)
lColl = TRUE
ENDIF
NEXT
NEXT
RETURN lColl
ENDFUNCTION // FNOBSTACLECOLLISION
fnDrawOverlay()
LOCAL lPrevX, lPrevY // stores previous coordinates
// save previous coordinates
lPrevX = tChar.x; lPrevY = tChar.y
// move character
IF lAngle <> -1
tChar.x = fnMoveX(lAngle, tChar.x, tChar.speed)
tChar.y = fnMoveY(lAngle, tChar.y, tChar.speed)
ENDIF
// check tile <<< NEW !!!
tChar.tileX = INTEGER( (tChar.x + 13) / 16)
tChar.tileY = INTEGER( (tChar.y + 8) / 16)
// check for obstacle collision / reset coordinates
IF fnObstacleCollision(tChar.x, tChar.y, 2, tChar.ani)
tChar.x = lPrevX; tChar.y = lPrevY
tChar.tileX = INTEGER( (tChar.x + 13) / 16)
tChar.tileY = INTEGER( (tChar.y + 8) / 16)
ENDIF
// load next map
IF tChar.x < 0 // west
DEC SectorX, 1
fnLoadMap()
tChar.x = 623
ENDIF
IF tChar.x > 623 // east
INC SectorX, 1
fnLoadMap()
tChar.x = 0
ENDIF
IF tChar.y < 0 // north
DEC SectorY, 1
fnLoadMap()
tChar.y = 463
ENDIF
IF tChar.y > 463 // south
INC SectorY, 1
fnLoadMap()
tChar.y = 0
ENDIF
// load tiles
LOADANIM "Tiles.png", 3, 16, 16
// load selector
LOADSPRITE "Selector.png", 4
// tile type for map
TYPE TTtile
ground[2]
obstacle
overlay
ENDTYPE
GLOBAL tMap[] AS TTtile
REDIM tMap[40][30]
// ------------------------------------------------------------- //
// --- FNDRAWTILES ---
// ------------------------------------------------------------- //
FUNCTION fnDrawTiles:
LOCAL lx, ly
// display tiles
FOR ly = 0 TO 29
FOR lx = 0 TO 39
// draw ground tiles
DRAWANIM 3, tMap[lx][ly].ground[0], lx * 16, ly * 16
DRAWANIM 3, tMap[lx][ly].ground[1], lx * 16, ly * 16
// draw obstacle tiles
DRAWANIM 3, tMap[lx][ly].obstacle, lx * 16, ly * 16
NEXT
NEXT
ENDFUNCTION // FNDRAWTILES
CONSTANT cNUM_TILES = 76 // number of tiles
// choosen tile (editor)
GLOBAL eTile
// keypress-delay in frames
GLOBAL KeyDelay
// decrease key delay
DEC KeyDelay, 1
IF KeyDelay < 0; KeyDelay = 0; ENDIF
STATIC lLayer // 0 = ground; 1 = obstacle; 2 = overlay
STATIC lGround = 1, lObstacle = 1, lOverlay = 1
LOCAL lx, ly
LOCAL lMapX, lMapY
LOCAL lLoop = TRUE
KeyDelay = 7
REPEAT
// read mouse state
GOSUB subReadMouse
// compute map x/y tile
lMapX = mx / 16; lMapY = my / 16
// draw background color
DRAWRECT 0, 0, 640, 480, RGB(255, 0, 128)
// display tiles
FOR ly = 0 TO 29
FOR lx = 0 TO 39
IF lGround
// draw ground tiles
DRAWANIM 3, tMap[lx][ly].ground[0], lx * 16, ly * 16
DRAWANIM 3, tMap[lx][ly].ground[1], lx * 16, ly * 16
ENDIF
IF lObstacle
// draw obstacle tiles
DRAWANIM 3, tMap[lx][ly].obstacle, lx * 16, ly * 16
ENDIF
IF lOverlay
// draw overlay tiles
DRAWANIM 3, tMap[lx][ly].overlay, lx * 16, ly * 16
ENDIF
NEXT
NEXT
// draw selected tile / selector
IF mbr = FALSE
DRAWANIM 3, eTile, INTEGER(mx) / 16 * 16, INTEGER(my) / 16 * 16
ELSE
DRAWSPRITE 4, INTEGER(mx) / 16 * 16, INTEGER(my) / 16 * 16
ENDIF
// draw mouse pointer
DRAWSPRITE 1, mx-15, my-15
// display layer information
ALPHAMODE -0.7
SELECT lLayer
CASE 0; PRINT "Ground Mode", 0, 0
CASE 1; PRINT "Obstacle Mode", 0, 0
CASE 2; PRINT "Overlay Mode", 0, 0
ENDSELECT
// display coordinates
PRINT SectorX +"/"+ SectorY, 0, 16
ALPHAMODE 0
// set tile
IF mbl // left mouse button
SELECT lLayer
CASE 0 // ground
IF KEY(42) // [LEFT SHIFT]
tMap[lMapX][lMapY].ground[1] = eTile
ELSE
tMap[lMapX][lMapY].ground[0] = eTile
ENDIF
CASE 1 // obstacle
tMap[lMapX][lMapY].obstacle = eTile
CASE 2 // overlay
tMap[lMapX][lMapY].overlay = eTile
ENDSELECT
ENDIF
// delete tile
IF mbr // right mouse button
SELECT lLayer
CASE 0 // ground
IF KEY(42) // [LEFT SHIFT]
tMap[lMapX][lMapY].ground[1] = 0
ELSE
tMap[lMapX][lMapY].ground[0] = 0
ENDIF
CASE 1 // obstacle
tMap[lMapX][lMapY].obstacle = 0
CASE 2 // overlay
tMap[lMapX][lMapY].overlay = 0
ENDSELECT
ENDIF
// pick tile
IF mbm // middle mouse button
SELECT lLayer
CASE 0 // ground
IF KEY(42) // [LEFT SHIFT]
eTile = tMap[lMapX][lMapY].ground[1]
ELSE
eTile = tMap[lMapX][lMapY].ground[0]
ENDIF
CASE 1 // obstacle
eTile = tMap[lMapX][lMapY].obstacle
CASE 2 // overlay
eTile = tMap[lMapX][lMapY].overlay
ENDSELECT
ENDIF
// decrease key delay
DEC KeyDelay, 1
IF KeyDelay < 0; KeyDelay = 0; ENDIF
// make layers visible/invisible
IF KEY(72) AND KeyDelay = 0 // [ZB8]
lOverlay = 1 - lOverlay
KeyDelay = 7
ENDIF
IF KEY(76) AND KeyDelay = 0 // [ZB5]
lObstacle = 1 - lObstacle
KeyDelay = 7
ENDIF
IF KEY(80) AND KeyDelay = 0 // [ZB2]
lGround = 1 - lGround
KeyDelay = 7
ENDIF
// select layer
// overlay
IF KEY(71) // [ZB7]
lLayer = 2
ENDIF
// obstacle
IF KEY(75) // [ZB4]
lLayer = 1
ENDIF
// ground
IF KEY(79) // [ZB1]
lLayer = 0
ENDIF
// quit editor mode
IF KEY(15) AND KeyDelay = 0 // [TAB]
lLoop = FALSE
KeyDelay = 7
ENDIF
SHOWSCREEN
UNTIL lLoop = FALSE
// set resolution / set to full screen
SETSCREEN 640, 480, 1
// set frames per second to 30
LIMITFPS 30
// load player character animation
LOADANIM "Character.png", 2, 26, 16
// main character data
TYPE TTchar
x // x coordinate
y // y coordinate
ani // animation index
speed // movement speed in pixel per frame
AniChron[8] // for animation chronology
ENDTYPE
GLOBAL tChar AS TTchar // create instance
DIMDATA tChar.AniChron[], 1, 2, 1, 0, 3, 4, 3, 0 // set animation chronology
LOCAL lMoveDir // stores movement-"bits"
LOCAL lAngle // movement angle
STATIC lStoreDir = 15 // saves animation if character stands
STATIC lMoveCnt // current index of animation cycle
// check arrow-keys / set movement-"bits"
IF KEY(30) // [A] Left/ bit: 0001
INC lMoveDir, 1
ELSE
IF KEY(32) // [D] Right / bit: 0010
INC lMoveDir, 10
ENDIF
ENDIF
IF KEY(17) // [W] Up / bit: 0100
INC lMoveDir, 100
ELSE
IF KEY(31) // [S] Down / bit: 1000
INC lMoveDir, 1000
ENDIF
ENDIF
// translate movement-"bits" into movement direction
// set true 45 degree movement-angle
// set animation frame
SELECT lMoveDir
CASE 1 // west
lMoveDir = 0 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 360 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 10 // east
lMoveDir = 5 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 180 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 100 // north
lMoveDir = 10 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 90 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 1000 // south
lMoveDir = 15 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 270 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 101 // north-west
lMoveDir = 0 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 45 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 110 // north-east
lMoveDir = 5 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 135 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 1010 // south-east
lMoveDir = 5 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 225 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 1001 // south-west
lMoveDir = 0 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 315 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
DEFAULT
lMoveCnt = 0 // reset counter
lAngle = -1 // sets movement angle
// set animation frame
tChar.ani = lStoreDir
ENDSELECT
// move character
IF lAngle <> -1
tChar.x = fnMoveX(lAngle, tChar.x, tChar.speed)
tChar.y = fnMoveY(lAngle, tChar.y, tChar.speed)
ENDIF
// increment/reset animation cycle
INC lMoveCnt, 0.4
IF lMoveCnt > 7; lMoveCnt = 0; ENDIF // reset animation
// initialize character values
tChar.x = 307; tChar.y = 232
tChar.speed = 3
fnComputeChar()
DRAWANIM 2, tChar.ani, tChar.x, tChar.y
// --------------------------------- //
// Project: Tutorial Game
// --------------------------------- //
//_____________________________________________________________________________ DECLARATIONS
//............................................................................... CONs
Constants:
//............................................................................... VARs
Variables:
// mouse state variables
GLOBAL mx, my // mouse coordinates
GLOBAL mbl, mbm, mbr // mouse button left, middle, right
GLOBAL mxspeed, myspeed, mwheel // mouse x speed, y speed, mouse wheel
// main directory
GLOBAL MainDir$
//............................................................................... DIMs
DIMs:
//.............................................................................. TYPEs
TYPes:
// main character data
TYPE TTchar
x // x coordinate
y // y coordinate
ani // animation index
speed // movement speed in pixel per frame
AniChron[8] // for animation chronology
ENDTYPE
GLOBAL tChar AS TTchar // create instance
DIMDATA tChar.AniChron[], 1, 2, 1, 0, 3, 4, 3, 0 // set animation chronology
//______________________________________________________________________________________ INI
// main initialization
GOSUB subINI
//________________________________________________________________________________ MAIN LOOP
MainLoop:
WHILE TRUE
// read mouse state
GOSUB subReadMouse
//...................................................................... MAIN CODE >>>
fnComputeChar()
DRAWANIM 2, tChar.ani, tChar.x, tChar.y
//...................................................................... <<< MAIN CODE
// draw mouse pointer
DRAWSPRITE 1, mx-15, my-15
// draw buffer on screen
SHOWSCREEN
WEND
//_________________________________________________________________________ SUBs / FUNCTIONs
// ------------------------------------------------------------- //
// -=# SUBINI #=-
// .............................................................
// main initialization
// ------------------------------------------------------------- //
SUB subINI:
// set resolution / set to full screen
SETSCREEN 640, 480, 1
// set frames per second to 30
LIMITFPS 30
// initialize character values
tChar.x = 307; tChar.y = 232
tChar.speed = 3
//.................................................. LOAD GFX
GFX:
// get main/set GFX directory
MainDir$ = GETCURRENTDIR$()
SETCURRENTDIR(MainDir$ + "Media/GFX")
// load standard font-gfx : index 0
LOADFONT "smalfont.png", 0 // standard font
// set font index
SETFONT 0 // standard font
// mouse pointer
LOADSPRITE "MPointer.png", 1
// load player character animation
LOADANIM "Character.png", 2, 26, 16
//.................................................. LOAD SFX
SFX:
SETCURRENTDIR(MainDir$ + "Media/SFX")
//................................................ LOAD MUSIC
Music:
SETCURRENTDIR(MainDir$ + "Media/Music")
// reset to main directory
SETCURRENTDIR(MainDir$)
ENDSUB // SUBINI
// ------------------------------------------------------------- //
// -=# SUBREADMOUSE #=-
// .............................................................
// reads various mouse states
// ------------------------------------------------------------- //
SUB subReadMouse:
// write mouse state into variables
MOUSESTATE mx, my, mbl, mbr // x coord, y coord, left button, right button
mxspeed = MOUSEAXIS(0) // x axis (x speed)
myspeed = MOUSEAXIS(1) // y axis (y speed)
mwheel = MOUSEAXIS(2) // wheel (1 = up / -1 = down)
mbm = MOUSEAXIS(5) // middle button
ENDSUB // SUBREADMOUSE
// ------------------------------------------------------------- //
// --- FNCOMPUTECHAR ---
// ------------------------------------------------------------- //
FUNCTION fnComputeChar:
LOCAL lMoveDir // stores movement-"bits"
LOCAL lAngle // movement angle
STATIC lStoreDir = 15 // saves animation if character stands
STATIC lMoveCnt // current index of animation cycle
// check arrow-keys / set movement-"bits"
IF KEY(30) // [A] Left/ bit: 0001
INC lMoveDir, 1
ELSE
IF KEY(32) // [D] Right / bit: 0010
INC lMoveDir, 10
ENDIF
ENDIF
IF KEY(17) // [W] Up / bit: 0100
INC lMoveDir, 100
ELSE
IF KEY(31) // [S] Down / bit: 1000
INC lMoveDir, 1000
ENDIF
ENDIF
// translate movement-"bits" into movement direction
// set true 45 degree movement-angle
// set animation frame
SELECT lMoveDir
CASE 1 // west
lMoveDir = 0 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 360 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 10 // east
lMoveDir = 5 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 180 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 100 // north
lMoveDir = 10 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 90 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 1000 // south
lMoveDir = 15 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 270 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 101 // north-west
lMoveDir = 0 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 45 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 110 // north-east
lMoveDir = 5 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 135 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 1010 // south-east
lMoveDir = 5 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 225 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
CASE 1001 // south-west
lMoveDir = 0 // set animation frame
lStoreDir = lMoveDir // saves animation frame
lAngle = 315 // sets movement angle
// set animation frame with incrementor
tChar.ani = lMoveDir + tChar.AniChron[lMoveCnt]
DEFAULT
lMoveCnt = 0 // reset counter
lAngle = -1 // sets movement angle
// set animation frame
tChar.ani = lStoreDir
ENDSELECT
// move character
IF lAngle <> -1
tChar.x = fnMoveX(lAngle, tChar.x, tChar.speed)
tChar.y = fnMoveY(lAngle, tChar.y, tChar.speed)
ENDIF
// increment/reset animation cycle
INC lMoveCnt, 0.4
IF lMoveCnt > 7; lMoveCnt = 0; ENDIF // reset animation
ENDFUNCTION // FNCOMPUTECHAR
// ------------------------------------------------------------- //
// -=# FNMOVEX #=-
// ------------------------------------------------------------- //
FUNCTION fnMoveX: lAngle, lx, lSpeed
DEC lAngle, 180
lx = lx + COS(lAngle) * lSpeed
RETURN lx
ENDFUNCTION // FNMOVEX
// ------------------------------------------------------------- //
// -=# FNMOVEY #=-
// ------------------------------------------------------------- //
FUNCTION fnMoveY: lAngle, ly, lSpeed
DEC lAngle, 180
ly = ly + SIN(lAngle) * lSpeed
RETURN ly
ENDFUNCTION // FNMOVEY
// --------------------------------- //
// Project: ExampleTemplate
// --------------------------------- //
//_____________________________________________________________________________ DECLARATIONS
//............................................................................... CONs
Constants:
//............................................................................... VARs
Variables:
// mouse state variables
GLOBAL mx, my // mouse coordinates
GLOBAL mbl, mbm, mbr // mouse button left, middle, right
GLOBAL mxspeed, myspeed, mwheel // mouse x speed, y speed, mouse wheel
// main directory
GLOBAL MainDir$
//............................................................................... DIMs
DIMs:
//.............................................................................. TYPEs
TYPes:
//______________________________________________________________________________________ INI
// main initialization
GOSUB subINI
//________________________________________________________________________________ MAIN LOOP
MainLoop:
WHILE TRUE
// read mouse state
GOSUB subReadMouse
//...................................................................... MAIN CODE >>>
//...................................................................... <<< MAIN CODE
// draw mouse pointer
DRAWSPRITE 1, mx-15, my-15
// draw buffer on screen
SHOWSCREEN
WEND
//_________________________________________________________________________ SUBs / FUNCTIONs
// ------------------------------------------------------------- //
// -=# SUBINI #=-
// .............................................................
// main initialization
// ------------------------------------------------------------- //
SUB subINI:
//.................................................. LOAD GFX
GFX:
// get main/set GFX directory
MainDir$ = GETCURRENTDIR$()
SETCURRENTDIR(MainDir$ + "Media/GFX")
// load standard font-gfx : index 0
LOADFONT "smalfont.png", 0 // standard font
// set font index
SETFONT 0 // standard font
// mouse pointer
LOADSPRITE "MPointer.png", 1
//.................................................. LOAD SFX
SFX:
SETCURRENTDIR(MainDir$ + "Media/SFX")
//................................................ LOAD MUSIC
Music:
SETCURRENTDIR(MainDir$ + "Media/Music")
// reset to main directory
SETCURRENTDIR(MainDir$)
ENDSUB // SUBINI
// ------------------------------------------------------------- //
// -=# SUBREADMOUSE #=-
// .............................................................
// reads various mouse states
// ------------------------------------------------------------- //
SUB subReadMouse:
// write mouse state into variables
MOUSESTATE mx, my, mbl, mbr // x coord, y coord, left button, right button
mxspeed = MOUSEAXIS(0) // x axis (x speed)
myspeed = MOUSEAXIS(1) // y axis (y speed)
mwheel = MOUSEAXIS(2) // wheel (1 = up / -1 = down)
mbm = MOUSEAXIS(5) // middle button
ENDSUB // SUBREADMOUSE
// ------------------------------------------------------------- //
// -=# FNMOVEX #=-
// ------------------------------------------------------------- //
FUNCTION fnMoveX: lAngle, lx, lSpeed
DEC lAngle, 180
lx = lx + COS(lAngle) * lSpeed
RETURN lx
ENDFUNCTION // FNMOVEX
// ------------------------------------------------------------- //
// -=# FNMOVEY #=-
// ------------------------------------------------------------- //
FUNCTION fnMoveY: lAngle, ly, lSpeed
DEC lAngle, 180
ly = ly + SIN(lAngle) * lSpeed
RETURN ly
ENDFUNCTION // FNMOVEY
// ------------------------------------------------------------- //
// -=# FNGETANGLE #=-
// ................................................................
// computes angle between two points
// ------------------------------------------------------------- //
FUNCTION fnGetAngle: lx1, ly1, lx2, ly2
LOCAL lAngle
// ??? angle-computing-code
lAngle = MOD((ATAN(ly1-ly2,lx1-lx2)+360),360)
RETURN lAngle
ENDFUNCTION // FNGETANGLE
// ------------------------------------------------------------- //
// -=# FNGETDISTANCE #=-
// ------------------------------------------------------------- //
FUNCTION fnGetDistance: lx1, ly1, lx2, ly2
LOCAL lx, ly, lReturn
lx = lx1 - lx2
ly = ly1 - ly2
// ??? distance computing code
lReturn = SQR( ABS(lx * lx) + ABS(ly * ly) )
RETURN lReturn
ENDFUNCTION // FNGETDISTANCE
Quotehat er das Programm installiert nach C:\Programme?
QuoteWelche Datei hat gefehlt?