Code:
'=======================================================
' Cat and Mouse
' The purpose of this short game is as an example :
' - random maze generator
' - the red creature is smile when he see and chase you
' - to be used for further maze game development
'
' Acknowledgement :
' - Farmer Man, The second game written in N7 by Marcus
' - MazeGen, converted from QB64 to N7 by Johnno
'=======================================================
'----------------
' INITIALIZATION
'----------------
include "assets/mazegen.n7"
set window "Cat and Mouse", 240, 222, false, 3
set redraw off
' Directions.
constant NONE = 0, LEFT = 1, RIGHT = 2, UP = 3, DOWN = 4
'color definition
visible white = [255,255,255]
visible black = [0,0,0]
visible player, opponent, map
InitialValue()
'-------------
' GAME LOOP
'-------------
do
set color black;cls;set color white
' Update
player.Update()
opponent.Update()
' Draw
map.Draw()
opponent.Draw()
player.Draw()
player.Win()
redraw
fwait 60
until keydown(KEY_ESCAPE,true)
'-----------
' FUNCTONS
'-----------
function InitialValue()
' Load map
generate_maze()
map = LoadMap("assets/map.txt")
map.img = loadimage("assets/tiles.png", 4, 1)
' Add player and enemies.
player = Player(map, 1, 0)
opponent = Enemy(map,14,11,loadimage("assets/red.png",4,2))
opponent.SetPlayer(player)
player.pacManMode = true
endfunc
function Map()
map = []
map.Obstacle = function(x, y)
c = this.map[x%this.w][y%this.h]
return c = 1
endfunc
map.CanMove = function(x, y, dir)
select dir
case LEFT return not this.Obstacle(x - 1, y)
case RIGHT return not this.Obstacle(x + 1, y)
case UP return not this.Obstacle(x, y - 1)
case DOWN return not this.Obstacle(x, y + 1)
default return true
endsel
endfunc
map.PickUp = function(x, y)
x = x%this.w
y = y%this.h
c = this.map[x][y]
return c
endfunc
map.DrawSprite = function(s)
x = s.x + this.offsetX
y = s.y
f = s.baseFrame + s.frame
draw image s.img, x, y, f
endfunc
map.Draw = function()
for y = 0 to this.h - 1
for x = 0 to this.w - 1
if this.map[x][y]
draw image this.img, this.offsetX + x*16, y*16, this.map[x][y]
endif
next
next
endfunc
map.w = 0
map.h = 0
map.map = unset
map.img = unset
map.offsetX = 0
return map
endfunc
function LoadMap(filename)
f = openfile(filename)
map = Map()
map.w = 15
map.h = 13
map.pw = map.w*16
map.ph = map.h*16
map.map = fill(0, map.w, map.h)
map.flags = []
for y = 0 to map.h - 1
for x = 0 to map.w - 1
c = fread(f)
map.map[x][y] = c
next
next
free file f
return map
endfunc
function Sprite(map, x, y, img)
s = []
s.StartMove = function(dir)
if this.moving or dir = NONE return false
ix = int(this.x/16)
iy = int(this.y/16)
if this.map.CanMove(ix, iy, dir)
this.dir = dir
select dir
case LEFT
this.dx = -1
this.dy = 0
this.dstX = int(this.x) - 16
this.dstY = int(this.y)
case RIGHT
this.dx = 1
this.dy = 0
this.dstX = int(this.x + 16)
this.dstY = int(this.y)
case UP
this.dx = 0
this.dy = -1
this.dstX = int(this.x)
this.dstY = int(this.y - 16)
case DOWN
this.dx = 0
this.dy = 1
this.dstX = int(this.x)
this.dstY = int(this.y + 16)
endsel
this.moving = true
endif
return this.moving
endfunc
s.Move = function()
if this.moving
this.x = this.x + this.dx*this.spd
this.y = this.y + this.dy*this.spd
if int(this.x) = this.dstX and int(this.y) = this.dstY
this.moving = false
this.x = (int(this.x/16)%this.map.w)*16
this.y = (int(this.y/16)%this.map.h)*16
endif
endif
return this.moving
endfunc
s.Draw = function()
set color white
this.map.DrawSprite(this)
endfunc
s.map = map
s.dir = NONE
s.moving = false
s.spd = 1
s.x = x*16
s.y = y*16
s.dx = 0
s.dy = 0
s.img = img
s.baseFrame = 0
s.frame = 0
return s
endfunc
function Player(map, x, y)
p = Sprite(map, x, y, loadimage("assets/player1.png"))
p.Update = function()
this.hitTimer = max(this.hitTimer - 1, 0)
item = this.map.PickUp(int((this.x + 8)/16), int((this.y + 8)/16))
this.Move()
if not this.moving
if keydown(KEY_LEFT) this.StartMove(LEFT)
if keydown(KEY_RIGHT) this.StartMove(RIGHT)
if keydown(KEY_UP) this.StartMove(UP)
if keydown(KEY_DOWN) this.StartMove(DOWN)
if this.pacManMode and not this.moving this.StartMove(this.dir)
endif
this.frame = 0
endfunc
p.Draw = function()
if this.hitTimer%4 < 2 this.map.DrawSprite(this)
endfunc
p.Win = function()
if this.x = 14*16 then
set color black;draw rect 20,height(primary)-12,width(primary),12,1
set color white; set caret 20,height(primary)-12
wln "At the Exit Door..ENTER"
redraw
temp = rln()
InitialValue()
endif
endfunc
p.pacManMode = false
p.hitTimer = 0
return p
endfunc
function Enemy(map, x, y, img)
e = Sprite(map, x, y, img)
e.SetPlayer = function(player)
this.player = player
endfunc
e.PossibleDirections = function()
dirs = []
x = int(this.x/16)
y = int(this.y/16)
if not this.map.Obstacle(x - 1, y) dirs[sizeof(dirs)] = LEFT
if not this.map.Obstacle(x + 1, y) dirs[sizeof(dirs)] = RIGHT
if not this.map.Obstacle(x, y - 1) dirs[sizeof(dirs)] = UP
if not this.map.Obstacle(x, y + 1) dirs[sizeof(dirs)] = DOWN
return dirs
endfunc
e.CanSeePlayer = function(dirs)
if this.player
dx = this.player.x - this.x
dy = this.player.y - this.y
ix = int(this.x/16)
iy = int(this.y/16)
px = int(this.player.x/16)
py = int(this.player.y/16)
foreach dir in dirs
select dir
case LEFT
if dx < 0 and |dy| < 16
for x = ix to px if this.map.Obstacle(x, iy) break
if x < px return LEFT
endif
case RIGHT
if dx > 0 and |dy| < 16
for x = ix to px if this.map.Obstacle(x, iy) break
if x > px return RIGHT
endif
case UP
if dy < 0 and |dx| < 16
for y = iy to py if this.map.Obstacle(ix, y) break
if y < py return UP
endif
case DOWN
if dy > 0 and |dx| < 16
for y = iy to py if this.map.Obstacle(ix, y) break
if y > py return DOWN
endif
endsel
next
endif
return NONE
endfunc
e.AtWall = function(dirs)
for i = 0 to sizeof(dirs) - 1
if dirs[i] = this.dir return false
next
return true
endfunc
e.AtCrossing = function(dirs)
if this.dir = LEFT or this.dir = RIGHT
for i = 0 to sizeof(dirs) - 1
if dirs[i] = UP or dirs[i] = DOWN return true
next
else
for i = 0 to sizeof(dirs) - 1
if dirs[i] = LEFT or dirs[i] = RIGHT return true
next
endif
return false
endfunc
e.Update = function()
if this.pause > 0
this.pause = this.pause - 1
this.frame = 0
else
if not this.Move() this.AtNewPosition(this.PossibleDirections())
if this.sawPlayer then
this.baseFrame = 4
set color white; set caret 20,height(primary)-12
wln "The Red : I can see you"
else
this.baseFrame = 0
set color white; set caret 20,height(primary)-12
wln "The Red : Where are you ?"
endif
this.frame = (this.frame + 0.2*this.spd)%4
endif
endfunc
e.AtNewPosition = function(dirs)
if this.AtWall(dirs)
dir = this.CanSeePlayer(dirs)
if dir
this.spd = 0.8
this.sawPlayer = true
else
this.spd = 0.4
if this.sawPlayer this.pause = 60
dir = dirs[rnd(sizeof(dirs))]
this.sawPlayer = false
endif
this.StartMove(dir)
else
if not this.sawPlayer and this.CanSeePlayer(this.dir)
this.spd = 0.8
this.sawPlayer = true
endif
this.StartMove(this.dir)
endif
endfunc
e.spd = 0.4
e.player = unset
e.sawPlayer = false
e.pause = 60 + rnd(3)*60
dirs = e.PossibleDirections()
e.StartMove(dirs[rnd(sizeof(dirs))])
return e
endfunc