Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- title: starship
- -- author: wesley werner
- -- desc: for ludum dare #39, theme:
- -- running out of power.
- -- you pilot a starship and recharge
- -- your fuel cells from solar radiation.
- -- z: shields
- -- x: fire phasers
- -- script: lua
- IDDQD=false
- -- screen size in pixels
- MAP_W=240
- MAP_H=136
- -- screen size in map cells
- CELLS_W=MAP_W/8
- CELLS_H=MAP_H/8
- -- other wessels in play
- MAX_WESSELS=30
- -- minimum distance for attack
- FIRING_RANGE=4
- SFX_BEAM=4
- SFX_CHARGE=2
- SFX_EXPLODE=3
- -- ticks to pass before closing a message box
- READ_TIMEOUT=100
- t=0
- -- variables
- state="intro"
- mapx=90
- mapy=50
- wessels={}
- plr=nil
- stars={}
- suns=nil
- hazards={}
- planets=nil
- mission=nil
- -- each new mission destination planet
- -- gets a name and this list is reduced.
- -- when all names are used up the game
- -- is won. there is a chance that a
- -- planet is called upon again, in that
- -- case the names list is not reduced.
- planet_names={
- "Hadrian",
- "Knara Prime",
- "Frixion Prime",
- "Epona",
- "Zelos",
- "Carina 3",
- "Vendrizi 9",
- "Beta Atheni",
- "Helion 8",
- "Arkanna",
- }
- mission_types={
- {note="escort ambassador Spock",
- result="He says to live long and prosper"},
- {note="transport some medical supplies",
- result="You join them in a celebratory meal"},
- {note="deliver much needed vacines",
- result="The planet rejoyces at your arrival"},
- {note="deliver sealed containers",
- result="You get a brief thanks"},
- {note="escort admiral kurtz",
- result="You receive his gratitude"},
- {note="transport plasma infusers",
- result="You feel pretty good about it"},
- {note="escort ambassador Sarek",
- result="He asks somberly about Spock"},
- {note="deliver some food rations",
- result="You are praised for your effort"},
- {note="locate missing commander Data",
- result="He was rescued from mercinaries"},
- }
- function init_wessels()
- -- define the wessels in play.
- -- the player is wessel 1 and has a
- -- unique position - it stays centred
- wessels[1]={
- sprite=256,
- x=105, -- position in map coords
- y=60,
- speed=1, -- move speed
- xvel=0, -- movement velocity
- yvel=0,
- power=100
- }
- --AI WESSELS
- for i=2,MAX_WESSELS do
- wessels[i]={
- sprite=272,
- x=math.floor(math.random()*MAP_W),
- y=math.floor(math.random()*MAP_H),
- speed=0.1, -- move speed
- xvel=0, -- movement velocity
- yvel=0,
- power=50
- }
- end
- end
- function init_player()
- plr=wessels[1]
- end
- function init_hazards()
- -- define hazardous tiles
- -- speed=factor (0 blocks)
- local ice={
- name="ice nebula",
- speed=0.5,
- }
- local fire={
- name="fire nebula",
- speed=0.2,
- }
- local elec={
- name="electric nebula",
- speed=0.7,
- }
- hazards={
- [145]=ice,
- [160]=ice,
- [161]=ice,
- [162]=ice,
- [177]=ice,
- [148]=fire,
- [163]=fire,
- [164]=fire,
- [165]=fire,
- [180]=fire,
- [151]=elec,
- [166]=elec,
- [167]=elec,
- [168]=elec,
- [183]=elec,
- }
- end
- function engage()
- trace("warp factor 5 engage!")
- init_planets()
- init_suns()
- init_stars()
- init_wessels()
- init_player()
- init_hazards()
- end
- function init_stars()
- local n=30
- for i=1,n do
- stars[i]={
- x=math.random() * MAP_W,
- y=(i/n) * MAP_H,
- c=i%4==0 and 2 or i%9==0 and 8 or 3
- }
- end
- end
- function init_planets()
- -- catalogue planets on the map
- planets={}
- local sprites={
- [48]=true,
- [50]=true,
- [52]=true,
- [54]=true,
- [56]=true,
- [58]=true
- }
- for x=1,MAP_W do
- for y=1,MAP_H do
- local i=mget(x,y)
- if sprites[i] then
- table.insert(planets,{x=x,y=y,name=name})
- end
- end
- end
- end
- function init_suns()
- -- catalogue suns on the map
- suns={}
- local sprites={
- [16]=true,
- [18]=true,
- [20]=true,
- [22]=true,
- [24]=true,
- [26]=true,
- [28]=true,
- }
- for x=1,MAP_W do
- for y=1,MAP_H do
- local i=mget(x,y)
- if sprites[i] then
- table.insert(suns,{x=x,y=y,power=100})
- end
- end
- end
- end
- function update_suns()
- -- suns generate power
- if t%30==0 then
- for k,v in pairs(suns) do
- if v.power<100 then
- v.power = v.power+1
- end
- end
- end
- end
- function update_stars()
- for k,v in pairs(stars) do
- -- move as parallax to luminosity
- v.x = v.x - (v.c * plr.xvel * 0.01)
- v.y = v.y - (v.c * plr.yvel * 0.01)
- -- wrap stars
- if v.x<0 then
- v.x=MAP_W
- elseif v.x>MAP_W then
- v.x=0
- end
- if v.y<0 then
- v.y=MAP_H
- elseif v.y>MAP_H then
- v.y=0
- end
- end
- end
- function draw_sunpower()
- for k,v in pairs(suns) do
- if v.power>0 and in_view(v.x,v.y) then
- local color=14+(t%60)/30
- local x=8*(v.x-mapx+0.9)
- local y=8*(v.y-mapy+1.5)
- local radius=(v.power/100)*8+8
- circb(x,y,radius,color)
- end
- end
- end
- function draw_stars()
- for k,v in pairs(stars) do
- pix(v.x, v.y, v.c)
- end
- end
- function handle_input()
- if state=="play" then
- local delay = 6
- -- move left or right
- if btn(2) then
- plr.xvel=-plr.speed
- elseif btn(3) then
- plr.xvel=plr.speed
- else
- plr.xvel=0
- end
- -- move up or down
- if btn(0) then
- plr.yvel=-plr.speed
- elseif btn(1) then
- plr.yvel=plr.speed
- else
- plr.yvel=0
- end
- -- firing
- if btn(5) then
- plr.firing=true
- plr.shielded=false
- elseif btn(4) then
- plr.shielded=true
- plr.firing=false
- else
- plr.shielded=false
- plr.firing=false
- end
- elseif state=="mission review" then
- if t>READ_TIMEOUT then
- if btn()~=0 then
- state="play"
- end
- end
- elseif state=="mission success" then
- if t>READ_TIMEOUT then
- if btn()~=0 then
- mission=nil
- -- no more planet names left for
- -- missions means game win!
- if #planet_names==0 then
- state="win"
- else
- state="play"
- end
- end
- end
- elseif state=="intro" then
- if t>READ_TIMEOUT then
- if btn()~=0 then
- state="play"
- end
- end
- end
- end
- function track_map()
- -- map tracks the player
- if plr.xvel or plr.yvel then
- mapx=math.floor(plr.x)-(CELLS_W/2)%MAP_W
- mapy=math.floor(plr.y)-(CELLS_H/2)%MAP_H
- end
- end
- -- WESSEL MOVEMENT
- function update_wessels()
- if t%10==0 then
- for i=#wessels,1,-1 do
- local v=wessels[i]
- if i>1 then
- move_ai(v)
- if v.destroyed then
- table.remove(wessels,i)
- sfx(SFX_EXPLODE,"C-2",60)
- end
- end
- local x = v.x
- local y = v.y
- -- accelerate the wessel
- x=(x+v.xvel)%MAP_W
- y=(y+v.yvel)%MAP_H
- -- store orientation
- if v.xvel~=0 then
- v.orient = v.xvel<0 and 1 or 0
- end
- -- check for blocker sprites
- local m=mget(x,y)
- local hazard = hazards[m]
- if hazard then
- v.hazard_note=hazard.name
- if hazard.speed == 0 then
- -- blocks movement
- v.xvel = 0
- v.yvel = 0
- x = v.x
- y = v.y
- elseif hazard.speed then
- -- affects movement
- x = v.x + (v.xvel * hazard.speed)
- y = v.y + (v.yvel * hazard.speed)
- end
- else
- v.hazard_note=nil
- end
- v.x=x
- v.y=y
- end
- end
- end
- function move_ai(wessel)
- local r=math.random()
- -- random movement
- if r<0.1 then
- wessel.xvel=math.random(-1,1)
- elseif r>0.9 then
- wessel.yvel=math.random(-1,1)
- end
- -- attacks
- local d=dist(wessel.x,wessel.y,plr.x,plr.y)
- if d<FIRING_RANGE then
- -- in firing range
- wessel.firing=true
- -- player takes damage
- if not plr.shielded then
- plr.power=plr.power-5
- end
- -- enemy takes damage
- if plr.firing==true then
- wessel.power=wessel.power-5
- end
- -- enemy destroyed
- if wessel.power<0 then
- wessel.destroyed=true
- end
- -- play sound
- if plr.firing then
- sfx(SFX_BEAM,"C-5",20)
- else
- sfx(SFX_BEAM,"C-4",20)
- end
- else
- wessel.firing=false
- end
- end
- function draw_wessels()
- -- draw relative to map position
- for i,v in ipairs(wessels) do
- if in_view(v.x, v.y) then
- -- wessel sprite
- spr(v.sprite,
- screenx(v.x),
- screeny(v.y),
- 0, -- colorkey
- 2, -- scale
- v.orient)
- -- enemy wessel is firing
- if i>1 then
- if v.firing==true then
- line(
- screenx(v.x)+4,
- screeny(v.y)+4,
- screenx(plr.x)+4,
- screeny(plr.y)+4,
- (t%10)/5+13)
- -- wessel health bar
- rectb(
- screenx(v.x),
- screeny(v.y),
- math.max(1,16*(v.power/100)),
- 2,
- 9)
- -- draw player shield hit
- if plr.shielded then
- circb(
- screenx(plr.x)+8,
- screeny(plr.y)+8,
- (t%10)/5+12,
- 11)
- end
- end
- end
- end
- end
- end
- function screenx(n)
- -- converts a map tile to screen coord
- return 8*(n-mapx)
- end
- function screeny(n)
- -- converts a map tile to screen coord
- return 8*(n-mapy)
- end
- function draw_map()
- map(mapx,mapy,
- 30, -- width
- 17, -- height
- 0, -- offset x and y
- 0,
- 0 -- colorkey
- )
- end
- function draw_sector()
- local x=math.floor((mapx+(CELLS_W/2)%240)/30)+1
- local y=math.floor((mapy+(CELLS_H/2)%136)/17)+1
- print("SECT "..x..":"..y,160,0,7)
- -- minimap
- spr(266,220,0)
- spr(267,228,0)
- spr(282,220,8)
- spr(283,228,8)
- pix(218+(16*x/8),(16*y/8)-2,15)
- -- mission sector
- if mission then
- pix(mission.mapx,mission.mapy,6)
- end
- end
- function draw_powerbar()
- local pwr=(plr.power/100)*12
- local color=8
- if plr.charging then
- -- charging
- color=11
- print("+",0,1)
- elseif plr.power<30 then
- -- warning
- color=6
- print("!",0,(t%60)/30+1)
- end
- -- battery
- spr(270,8,0,0)
- spr(271,16,0,0)
- rect(9,2,pwr,4,color)
- -- shields
- if not plr.shielded then
- spr(268,26,0,0)
- else
- spr(269,26,0,0)
- end
- -- weapons
- if not plr.firing then
- spr(284,36,0,0)
- else
- spr(285,36,0,0)
- end
- -- print hazard note
- if plr.hazard_note and t%60>30 then
- print(plr.hazard_note,50,0,6)
- end
- end
- function dist(ax,ay,bx,by)
- local dx=math.pow(ax-bx,2)
- local dy=math.pow(ay-by,2)
- return math.sqrt(dx+dy)
- end
- function update_poweruse()
- -- player is on a sun
- if t%30==0 and plr.power<100 then
- plr.charging=false
- for k,sun in pairs(suns) do
- if sun.power>0 then
- if in_view(sun.x, sun.y) then
- -- player is near this sun
- local d=dist(sun.x,sun.y,plr.x,plr.y)
- if d<2 then
- plr.power=plr.power+8
- sun.power=sun.power-8
- plr.charging=true
- sfx(SFX_CHARGE,"E-1",80)
- -- set sun cooldown
- if sun.power<0 then
- sun.power=-100
- end
- end
- end
- end
- end
- end
- -- reduce player power while moving
- if t%10==0 and plr.power>0 then
- if plr.xvel~=0 or plr.yvel~=0 then
- plr.power = plr.power-1
- end
- end
- -- shielding and firing
- if t%10==0 then
- if plr.shielded==true then
- plr.power=plr.power-0.3
- elseif plr.firing==true then
- plr.power=plr.power-0.3
- end
- end
- -- death
- if plr.power<=0 then
- state="dead"
- sfx(SFX_EXPLODE,"C-2",120)
- end
- end
- function in_view(x, y)
- -- returns if the points are in view
- local dx = x-mapx
- local dy = y-mapy
- return dx>-3 and dx <CELLS_W and
- dy>=-3 and dy<CELLS_H
- end
- function draw_gameover()
- local x=MAP_W/4
- local y=MAP_H/3
- print("GAME OVER",x+1,y,2,false,2)
- print("GAME OVER",x,y,15,false,2)
- print("You ran out of power!",x+1,y*2,1)
- print("You ran out of power!",x,y*2,15)
- end
- function near_planet()
- -- gets a nearby planet
- for k,v in pairs(planets) do
- if in_view(v.x,v.y) then
- local d=dist(v.x,v.y,plr.x,plr.y)
- if not v.visited and d<2 then
- return v
- end
- end
- end
- end
- function far_planet()
- -- gets a remotely far planet
- local plan=nil
- while not plan do
- plan=planets[math.random(#planets)]
- local d=dist(plan.x,plan.y,plr.x,plr.y)
- if plan.visited or d<10 then
- plan=nil
- end
- end
- return plan
- end
- function update_mission()
- -- reduce processing
- if t%100~=0 then return end
- -- find nearby planet
- local planet=near_planet()
- if planet and mission then
- -- test mission success
- if mission.planet==planet.name then
- -- visited planets don't offer new missions
- planet.visited=true
- -- reset t: it controls input timeout
- state="mission success"
- t=0
- end
- elseif planet and not mission then
- -- get a new mission
- mission=mission_types[math.random(#mission_types)]
- -- to a remote planet
- local dest=far_planet()
- -- that should have a name
- if not dest.name then
- dest.name=table.remove(planet_names)
- end
- -- precalculate mission destination
- -- on minimap
- local mapx=math.floor(dest.x/30)+1
- local mapy=math.floor(dest.y/17)+1
- mapx=(16*mapx/8)+218
- mapy=(16*mapy/8)-2
- mission.planet=dest.name
- state="mission review"
- mission.mapx=mapx
- mission.mapy=mapy
- -- reset t: it controls input timeout
- t=0
- end
- end
- function draw_missionbar()
- -- draw current mission on screen
- if mission then
- printc(mission.note,120,130,3)
- end
- end
- function draw_box()
- rect(10,10,220,126,1)
- rectb(10,10,220,126,2)
- end
- function draw_mission_review()
- -- draw a mission review box
- if mission then
- draw_box()
- printc("NEW MISSION:",120,20,15)
- printc(mission.note,120,60,8)
- printc("destination: "..mission.planet,120,70,10)
- if t>READ_TIMEOUT then
- printc("press any key",120,120,7)
- end
- end
- end
- function draw_mission_success()
- -- draw a mission success box
- if mission then
- draw_box()
- printc("MISSION SUCCESS!",120,20,15)
- printc(mission.note,120,40,8)
- printc("to "..mission.planet,120,50,10)
- printc(mission.result,120,70,8)
- if t>READ_TIMEOUT then
- printc("press any key",120,120,7)
- end
- end
- end
- --Prints text where x is the center of text.
- function printc(s,x,y,c)
- local w=print(s,0,-8)
- print(s,x-(w/2),y,c or 15)
- end
- function draw_winscreen()
- draw_box()
- printc("After a long journey exploring",120,20,15)
- printc("the galaxy, you retire on the",120,30,15)
- printc("Eden planet, living in comfort",120,40,15)
- printc("while everyone delivers fresh",120,50,15)
- printc("fruit and craft cheeses to you.",120,60,15)
- printc("Ah this is the life!",120,70,14)
- printc("Created by wesley for Ludum Dare #39",120,80,13)
- printc("press ctrl-r to play again",120,128,7)
- -- wessel sprite
- spr(plr.sprite,
- 100,
- 80,
- 0, -- colorkey
- 6, -- scale
- plr.orient)
- end
- function draw_intro()
- draw_box()
- printc("Welcome!",120,20,15)
- printc("You are a starship captain, you explore",120,30,15)
- printc("the galaxy and help others on the way.",120,40,15)
- printc("Z key - engage shields",120,50,8)
- printc("X key - fire phasers (auto aims)",120,60,8)
- printc("Fly over suns to recharge your power",120,70,14)
- printc("Dock at planets to complete missions",120,80,14)
- printc("You retire after 10 missions",120,90,15)
- printc("restart the game with ctrl-R",120,100,15)
- printc("Created by wesley for Ludum Dare #39",120,110,13)
- printc("press any key",120,120,7)
- -- shield sprite
- spr(269,190,48,0,1)
- -- weapons sprite
- spr(285,210,58,0,1)
- end
- function TIC()
- cls(0)
- handle_input()
- if state=="play" then
- update_wessels()
- update_stars()
- update_suns()
- track_map()
- update_poweruse()
- update_mission()
- if IDDQD then plr.power=100 end
- end
- draw_stars()
- draw_sunpower()
- draw_map()
- draw_wessels()
- draw_powerbar()
- draw_missionbar()
- draw_sector()
- if state=="mission review" then
- draw_mission_review()
- elseif state=="mission success" then
- draw_mission_success()
- elseif state=="dead" then
- draw_gameover()
- elseif state=="win" then
- draw_winscreen()
- elseif state=="intro" then
- draw_intro()
- end
- t=t+1
- end
- engage()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement