wave and bullet class im working on. the intent is not to have a generic bullet class, but rather customize each wave and bullet…?
anyway, added a freeze/unfreeze function after i paused and unpausrd by accident and saw something really cool!
-- bullet share
displayMode(OVERLAY)
displayMode(FULLSCREEN)
-- Use this function to perform your initial setup
function setup()
Player = {x=100,y=200,lv=1,hp=30,blinking=false,drawing=true,
Hurt=function(self,dmg,time)
if self.blinking then return end
self.hp=math.max(self.hp-dmg,0);
if self.hp==0 then sound(SOUND_EXPLODE, 5503)
else sound(SOUND_HIT); blink:start(time);
end
end}
blink = {parent = Player, time=0}
function blink:start(time)--call from Player.Hurt, call Player.Hurt in your bullet OnHit function
self.parent.blinking = true
self.tween=tween(time, self, {time=time},tween.easing.linear,self.finish,self)
tween.sequence(self.tween)
end
function blink:finish()
self.parent.blinking = false
self.parent.drawing = true
tween.reset(self.tween)
--self.time = 0
--self.tween = nil
end
function blink:update()
if not self.parent.blinking then return end
self.parent.drawing = self.time % 0.15 > 0.075
end
wave = firewave()
end
local alpha = 1
GameOver={}
function GameOver.draw()
background(0)
alpha = alpha < 255 and alpha + 1 or alpha
fill(100, alpha)
fontSize(72)
text('GAME OVER', WIDTH/2, HEIGHT/2)
end
function GameOver.touched(t)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
if Player.hp == 0 then
GameOver.draw()
return
end
background(40, 40, 50)
-- This sets the line thickness
pushStyle()
--text('LV '..Player.lv, WIDTH/2-100, 700)
text('HP '..Player.hp..'/'..26+Player.lv*4,WIDTH/2, 700)
if Player.drawing then
fill(254,112,33)
rectMode(CENTER)
rect(Player.x, Player.y, 24,24)
end
text('Score '..math.floor(ElapsedTime), WIDTH/2,740)
popStyle()
-- Do your drawing here
wave:draw()
wave:update()
blink:update()
--Player can go on the one sides of the screen and come out the other side
Player.x = Player.x > 1000 and 44 or Player.x < 24 and 980 or Player.x
Player.y = Player.y > 744 and 44 or Player.y < 24 and 724 or Player.y
end
function touched(t)
if t.deltaX < 0 then
Player.x=Player.x + math.max(t.deltaX, -8)
else
Player.x=Player.x + math.min(t.deltaX, 8)
end
if t.deltaY < 0 then
Player.y = Player.y + math.max(t.deltaY,-8)
else
Player.y = Player.y + math.min(t.deltaY,8)
end
end
--THESE ARE INDIVIDUAL BULLETS AND ONLY HANDLE THEMSELVES ON AN INDIVIDUAL BASIS
--for the wave script and patterns, make your own function
Fireball = class()
--actually, a mesh would work even better for memory
--cant remember how to flip a mesh when drawing it though
--so ill make two.
--hey, I have 16x16 images, should i use (0,0,16,16) or (0,0,15,15)?
--(but nows its 32x32 )
local spriteleft = mesh()
--spriteleft.texture = readImage("Project:spr_firebullet_center2_0")
spriteleft:addRect(0,0,32,32)--,16,16)
--spriteleft:setRectTex(1,0,0,1,1)
spriteleft:setRectColor(1, 155,123,32)
local spriteright = mesh()
--spriteright.texture = readImage("Project:spr_firebullet_center2_1")
spriteright:addRect(0,0,32,32)---16,-16,16,16)
--spriteright:setRectTex(1,0,0,1,1)
spriteright:setRectColor(1, 155,123,32)
--local direction = 'RIGHT'
--local RELATIVE, ABSOLUTE = 0,1
--UNUSED UNIFNISHED HELIX LOGIC FROM DESMOS
--[[
local d = 2.1
--local a--the variable that changes --use self.time instead
local c = 2
local b = 2
--]]
local xvelocities = {0.1,0.2}
function Fireball:init(x, y)
self.direction = math.random(1,2) == 2 and -1 or 1
self.time = 0
self.pos = vec2(x,y)
--try setting direction to be floats, i.e. -0.2 or 2 ;)
--self.velocity = vec2(math.random(5,20)/10*self.direction, math.random(500,501) / 500 * self.direction)
self.vel2 = vec2(math.random(), math.random())
--self.maxvelocity = {positive=vec2(50,50),negative=vec2(-50,-50)}
--p.s. try to keep calculations in init to save cpu
end
function Fireball:update()
self.time = self.time + DeltaTime
if self.pauseposition then
--self.position.y = self.position.y
return
end
--[[
--simple spiral example
self.pos.x = self.pos.x + self.time*math.sin(self.time)*self.direction
self.pos.y = self.pos.y - self.time*math.cos(self.time)
--]]
--[[
--fire goes down, up, down and up
--spawns with an initial y velocity!
--self.pos.x = self.pos.x + self.time*math.sin(self.time)*self.direction/5
--self.pos.y = self.pos.y - (self.time+math.random(1,20)/10)*math.cos(self.time)
--]]
-- tighter spiral
self.pos.x = self.pos.x + self.time*math.sin(self.time)*self.direction*self.vel2.x
self.pos.y = self.pos.y - self.time*math.cos(self.time)*self.vel2.y
--to do: helix
--self.pos.x..
if self.pos:dist(vec2(Player.x, Player.y)) < 24 then
self:OnHit()
end
end
function Fireball:draw(x,y,w,h)
pushMatrix()
translate(self.pos.x, self.pos.y)
if self.time % 0.2 > 0.1 then
--sprite(self.leftsprite, Arena.x + self.x, Arena.y + self.y, 16, 16)
spriteleft:draw()
else
--sprite(self.rightsprite, Arena.x + self.x, Arena.y + self.y, 16, 16)
spriteright:draw()
end
popMatrix()
--clip()
end
--[[PHYSICS DOESNT WORK
function Fireball:collide(contact)
if contact.state == BEGAN then
self:OnHit()
end
end
--]]
function Fireball:OnHit()
Player:Hurt(3, 0.5)--damage,invincibility time in seconds
--self:Remove()
end
function Fireball:Remove()
--self.time, self.x, self.y, self.velocity = nil,nil,nil,nil --does this actually work?
self=nil --maybe equivalent to the above..
end
--script
firewave = class()
function firewave:init()
self.time = 0
self.timer = 20
self.nextfireball_timer = 0.2
self.bullets = {}
self.x = WIDTH/2--Arena.x + (Arena.x2 - Arena.x) * 0.5
self.y = HEIGHT/2--Arena.y2 - 16
local o1=5 --offset bottom left corner
local o2=8 --offset top right corner
self.t1 = tween.delay(10, self.freeze, self)
self.t2 = tween.delay(1, self.unfreeze, self)
self.t3 = tween.delay(10, self.freeze, self)
self.t4 = tween.delay(1, self.unfreeze, self)
tween.sequence(self.t1, self.t2, self.t3, self.t4)
--disabled clip for this example
--self.clip = --{x=Arena.x+o1,y=Arena.y+o1,
--w=Arena.x2-Arena.x-o2, h=Arena.y2-Arena.y-o2}
--self.coroutine = coroutine.create(self.spawn, 20)
--coroutine.resume(self.coroutine, self, 20)
end
--currently doesn't handle its own destruction - but you can easily configure it to..
--i.e. in firewave:update say
--if self.time > self.timer then firewave:destroy()
function firewave:update(dt)
self:HandleMovement()
self.time = dt and self.time + dt or self.time + DeltaTime
if self.time >= self.nextfireball_timer then
if not self.frozen then table.insert(self.bullets, Fireball(self.x, self.y)) end
self.nextfireball_timer = self.nextfireball_timer + 0.4
end
end
function firewave:draw()
pushStyle()
--disable clip to see fullscreen bullet pattern
--clip(self.clip.x, self.clip.y, self.clip.w, self.clip.h)
for i,v in ipairs(self.bullets) do
v:draw()--self.clip.x, self.clip.y, self.clip.w, self.clip.h)
end
clip()
popStyle()
end
function firewave:destroy()
for i,v in ipairs(self.bullets) do
v:Remove() --in v, sets self.x, self.y, self.velocity and self.time to nil
v = nil --deletes all references from self.bullets
end
--self.coroutine = nil --doesn't kill coroutine just deletes reference; might need garbagecollect
--self = nil --is this equivalent to all of the above or would they stay in memory if i do that?
--return 'timer ended'
end
function firewave:HandleMovement()
for i,v in ipairs(self.bullets) do
v:update()
--was too lazy to code properly, please do this later
--you might use this if you had... say, a laser that spawned a wave of bullets
--make it fancy and cool, i.e. Touhou spellcards
end
end
function firewave:freeze()
self.frozen=true
for i,v in ipairs(self.bullets) do
v:freeze()
end
end
function firewave:unfreeze()
for i,v in ipairs(self.bullets) do
--v.velocity.y = v.velocity.y + 5
v:unfreeze()
end
self.frozen=false
end
function Fireball:freeze()
self.pauseposition = vec2(self.pos.x, self.pos.y)
end
function Fireball:unfreeze()
self.pauseposition = false
end