1
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.
We need a new version ?!
- 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
hat er das Programm installiert nach C:\Programme?
Welche Datei hat gefehlt?