cxr2 = arcade_config.character_per_row_base2 -- 4, 3 -- imp={hab=75, -- x=24, -- y=24, -- w=32, -- h=32, -- flip=true, -- enabled=false, -- counter=500, -- frame=28, -- wait=0, -- step=0, -- anim={28,29,28,30}, -- bb={x=4,y=0,w=16,h=32}, -- scene_intro=false, -- scene_object=false, -- fight_modes={"chase","away","super","shot"}, -- mode="stop", -- mode_cooldown=100} imp = {} function imp.reset() imp.hit=imp.hit imp.update=imp.update imp.draw=imp.draw imp.hab=abad.hab imp.enabled=false imp.counter=500 end function imp.new(_hab, _x, _y) local world_x, world_y = coords.room_to_world(_hab,_x,_y) _fight_modes={"chase","away","super","shot"} for i,v in ipairs(_fight_modes) do _fight_modes[v] = i end return { name="imp", hab=_hab, x=world_x, y=world_y, w=32, h=32, flip=true, frame=28, wait=0, vides=1, energia=6, max_energia=6, falling=0, step=0, hurting=0, jumpfwd=false, step_length=1, vmove_space=1, max_jump_height=24, jump_height=0, jump_in_half_block=0, jump_in_half_block_used = false, max_shoot_cooldown=24, shot_power=1, shot_num_shots=1, shoot_cooldown=25, anim={28,29,28,30}, bb={x=8,y=0,w=16,h=32}, scene_intro=false, scene_object=false, fight_modes=_fight_modes, mode="stop", mode_cooldown=1000, super_cooldown=2000, shot_cooldown=500, action="", movement="", enabled=true, disable_reason="", can_warp=false, fight=imp.fight, draw=imp.draw, hit=imp.hit, hot_points={}, target={}, old_target={}, invencible=false, -- direccio=imp.direccio, do_jump=imp.do_jump, jump=imp.jump, state_jumping=imp.state_jumping, chase=imp.chase, away=imp.away, move=imp.move, super=imp.super, shot=imp.shot, do_flip=imp.do_flip, update=imp.state_normal, land=imp.land, mode_controller=imp.mode_controller, movement=imp.movement, advance=imp.advance, reduce_cooldown=imp.reduce_cooldown, set_fight_mode=imp.set_fight_mode, think=imp.think, controller_input=imp.controller_input, ia=imp.ia, analyze_env=imp.analyze_env, -- imp.enabled=false -- imp.counter=500 } end function imp:fight() print("FIGHTING MODE") -- table.insert(self.hot_points, point.new(54,5,4,12,8,"P1")) -- table.insert(self.hot_points, point.new(44,5,3,12,8,"P2")) -- table.insert(self.hot_points, point.new(55,7,4,12,8,"P3")) -- table.insert(self.hot_points, point.new(45,7,3,12,8,"P4")) -- table.insert(self.hot_points, point.new(44,12,5,12,8,"P5")) -- table.insert(self.hot_points, point.new(54,12,4,12,8,"P6")) table.insert(self.hot_points, point.new(54, 5, 4, 0, 0,"P1")) table.insert(self.hot_points, point.new(44, 5, 3, 0, 0,"P2")) table.insert(self.hot_points, point.new(55, 8, 4, 0, 0,"P3")) table.insert(self.hot_points, point.new(45, 8, 3, 0, 0,"P4")) table.insert(self.hot_points, point.new(44,12, 5, 0, 0,"P5")) table.insert(self.hot_points, point.new(54,12, 4, 0, 0,"P6")) table.insert(self.hot_points, abad); self.target = self.hot_points[3] self.mode="chase" end function imp:draw() local scr_x, scr_y = viewp:screen_coords( self.x, self.y ) draw.surf((self.frame&7)*self.w, (self.frame>>cxr2)*self.h, self.w, self.h, scr_x, scr_y, self.w, self.h, self.flip) draw.rect(scr_x+self.bb.x,scr_y+self.bb.y,self.bb.w,self.bb.h,3) if #self.hot_points>0 then for _, p in pairs(self.hot_points) do if self.target==p then p:draw(true) else p:draw() end end end end function imp:hit() print("HIT!") end function imp:do_jump ( jumpfwd ) -- msg_print(0,0,"do_jump",true) -- Inicialització de fer el salt jumpfwd = jumpfwd or false self.jump_height = 0 self.update=imp.state_jumping self.step=0 self.jumpfwd=jumpfwd self.action="" end function imp:analyze_env() -- Distancia fins els punts local scr_x, scr_y = viewp:screen_coords(self.x, self.y) -- for _, p in pairs(self.hot_points) do -- local scr_x1, scr_y1 = viewp:screen_coords(p.x, p.y) -- local color = 2 -- if self.target == p then color = 4 end -- draw.line(scr_x, scr_y, scr_x1, scr_y1, color) -- -- dx = (self.x-p.x) -- dy = (self.y-p.y) -- d = math.sqrt(dx*dx+dy*dy) -- end -- Distancia fins a l'abad dx = (self.x-abad.x) dy = (self.y-abad.y) r = math.sqrt(dx*dx+dy*dy) -- msg_print(10,20,r,true) local can_chase_abad = false if r<=100 then -- draw.circ(scr_x+self.bb.w/2,scr_y+self.bb.h/2,r,2) can_chase_abad=true end -- Els dos punts de cintura per a saber si es pot escalar local x1_check = self.x+self.bb.x local x2_check = self.x+self.bb.x+self.bb.w local y_check = self.y+self.bb.h-4 local tile_type1, tile_code1= arc_check_tile(x1_check,y_check) local tile_type2, tile_code2= arc_check_tile(x2_check,y_check) local can_climb = false if tile_type1~=tiletype.void or tile_type2~=tiletype.void then can_climb = true end -- Abad a tir local can_shot = false if h_collision(self,abad) then can_shot=true end -- Super preparat local can_super = false if self.super_cooldown<=0 then can_super=true end -- Acces a la zona central x1_check = self.x+self.bb.x x2_check = self.x+self.bb.x+self.bb.w y_check = self.y+self.bb.h local can_go_altar = false local hab1, tx1, ty1 = coords.world_to_tile(x1_check, y_check) local hab2, tx2, ty2 = coords.world_to_tile(x2_check, y_check) if (hab1==44 and tx1==6 and ty1==4) or (hab2==44 and tx2==7 and ty2==4) or (hab1==45 and tx1==7 and ty1==3) or (hab2==45 and tx2==8 and ty2==3)then can_go_altar = true end -- Cau al següent moviment local going_to_fall = false local tile_type1, tile_code1= arc_check_tile(x1_check,y_check) local tile_type2, tile_code2= arc_check_tile(x2_check,y_check) if tile_type1==tiletype.void and tile_type2==tiletype.void then going_to_fall = true end local target_reached = false local target_aligned = false if #self.target>0 then -- Target reached if collision(self, self.target) then target_reached=true end -- Target aligned if half_collision(self, self.target) then target_aligned=true end end -- if can_climb then print("Climb!") end -- if can_shot then print("Shot!") end -- if can_super then print("Super!") end -- if can_go_altar then -- -- msg_print(10,20,"Altar READY!", true) -- print("Altar!") -- end -- msg_print(10,40,hab1..", "..tx1..", "..ty1, true) -- msg_print(10,60,hab2..", "..tx2..", "..ty2, true) end function imp:ia() self:reduce_cooldown() -- if self.update==imp.state_jumping or self.update==imp.state_falling then -- -- self:set_fight_mode() -- -- self:think() -- end self:analyze_env() if self.update==imp.state_walking or self.update==imp.state_normal then self:set_fight_mode() self:think() end self:controller_input() end function imp:state_jumping() -- msg_print(0,0,"state_jumping",true) -- ?? self.wait=self.wait+1 self.wait=0 -- Pujar o caure if self.jump_height0 then self.y=self.y-vspace self.jump_in_half_block = self.jump_in_half_block-1 self.jump_in_half_block_used = true end end end -- Registrar el desplaçament self.jump_height = self.jump_height+1 end function imp:state_walking() -- msg_print(16,48,"state_walking",true) -- Limitar la velocitat de moviment self.wait=self.wait+1 -- representació del moviment -- Selecció de frame if self.wait==6 then self.wait=0 self.step=(self.step+1)%4 self.frame=self.anim[self.step+1] end -- Comprovar dos punts de contacte del personatge en el piso a vore si cau local x1_check = self.x+self.bb.x local x2_check = x1_check+self.bb.w local y_check = self.y+self.bb.h; -- base del personatge local tile1 = arc_check_tile(x1_check,y_check) local tile2 = arc_check_tile(x2_check,y_check) if tile1==tiletype.void and tile2==tiletype.void then -- si no hi ha piso, caure self.update=imp.state_falling return end self:advance() self:ia() end function imp:state_falling() -- msg_print(16,16,"state_falling",true) self.frame=30 self.wait=self.wait+1 -- Si toca terra canviar el mode if self:land() then self.update=imp.state_normal return end -- Seguir caiguent self.y=self.y+1 self.jump_height = self.jump_height-1 self.falling=self.falling+1 -- Caiguent cap endavant? if self.jumpfwd then self:advance() end self:ia() end function imp:land () -- msg_print(16,32,"land",true) -- Els dos punts de baix de l'abad local x1_check = self.x+self.bb.x local x2_check = self.x+self.bb.x+self.bb.w local y_check = self.y+self.bb.h -- Comprovar on està aterrant local tile1_hit= arc_check_tile(x1_check, y_check ) local tile2_hit= arc_check_tile(x2_check, y_check) local floor_tile = tile1_hit>=tiletype.half or tile2_hit>=tiletype.half -- Encara que siga un tile de piso s'ha de comprovar que -- la y es un múltiple de l'alt dels tiles local over_tile = (y_check & 0xF) == 0 local can_land = floor_tile and over_tile if can_land then self.jump_in_half_block_used = false self.jump_height = 0 end return can_land end function imp:advance() -- msg_print(0,0,"advance",true) local step_length=self.step_length; --lo que avança el imp cada pas local limit=tiletype.block if self.update~=imp.state_walking then limit=tiletype.half end local x_check = self.x+self.bb.x+self.bb.w+step_length -- if self.flip then -- step_length = -step_length -- x_check = self.x+self.bb.x+step_length -- end -- self.action=="right" -- if self.action=="left" then if self.movement=="left" then step_length = -step_length x_check = self.x+self.bb.x+step_length end local y_check = self.y+self.bb.h-4 if arc_check_tile(x_check, y_check)=self.x+self.bb.x then action="right" elseif self.target.x+self.target.bb.xself.target.y or self.y=self.target.y+self.target.bb.y then -- local tile_type, tile_code = arc_check_tile(self.x+self.bb.x,self.y+self.bb.h, true) -- local tile_type2, tile_code2 = arc_check_tile(self.x+self.bb.x+self.bb.w,self.y+self.bb.h, true) -- msg_print(50, 50, tile_type..", "..tile_code, true ) -- if tile_type ~=tiletype.void or tile_type2 ~=tiletype.void then -- print("JUMP") -- action = "jump" -- else -- if self.target.x+self.target.bb.x>=self.x+self.bb.x then -- print("sense eixida") -- -- self.mode_cooldown = 0 -- -- self:set_fight_mode() -- end -- end -- -- elseif self.y==self.target.y and math.abs(self.x-self.target.x)<=8 then -- -- action = "jumpfwd" -- end -- local ix, iy = viewp:screen_coords( self.x, self.y ) -- draw.rect(ix+(self.bb.x+(self.bb.w/2)), iy+(self.h/2), 2,2, 2) -- if self.fight_modes[self.mode]=="away" or self.fight_modes[self.mode]=="chase" then -- if self.y>=self.target.y -- and arc_check_tile(self.x+(self.bb.x+(self.bb.w/2)),(self.y+(self.h/2)))~=tiletype.void then -- action = "jump" -- elseif self.y==self.target.y and math.abs(self.x-self.target.x)<=8 then -- action = "jumpfwd" -- else -- if self.fight_modes[self.mode]=="away" then -- if self.target.x<=self.x then -- action="right" -- else -- action="left" -- end -- elseif self.fight_modes[self.mode]=="chase" then -- if self.target.x>=self.x then -- action="right" -- else -- action="left" -- end -- end -- end -- elseif self.fight_modes[self.mode]=="super" then -- action="super" -- elseif self.fight_modes[self.mode]=="shot" then -- action="shot" -- end self.action = action return action end function imp:reduce_cooldown() if self.mode=="stop" then return end self.mode_cooldown = self.mode_cooldown -1 self.super_cooldown = self.super_cooldown -1 self.shoot_cooldown = self.shoot_cooldown -1 end ------------------------------- -- imp.set_fight_mode() -- -- Cridar en cada iteració per -- a canviar el mode de lluita ------------------------------- function imp:set_fight_mode() if self.mode=="stop" then return end if self.mode_cooldown <= 0 then -- seleccionar mode d'acció local last_mode=self.mode -- self.mode_cooldown = 150+math.random(50)-1 self.mode_cooldown = 1000 -- self.mode=math.random(#self.fight_modes) -- -- if self.mode==self.fight_modes["super"] and self.super_cooldown>0 then self.mode=self.fight_modes["shot"] end -- if self.mode==self.fight_modes["shot"] and self.shot_cooldown>0 then self.mode=self.fight_modes["chase"] end self.mode=self.fight_modes["chase"] -- print("cambiar modo => "..self.fight_modes[self.mode]) local new_point = math.random(#self.hot_points) if self.target == self.hot_points[new_point] then new_point = ((new_point+1)%#self.hot_points)+1 end self.old_target = self.target self.target=self.hot_points[new_point] print("target => "..self.target.id) end -- -- if self.mode==last_mode then self.mode=((last_mode+1)%#self.fight_modes)+1 end -- elseif self.mode_cooldown == 0 then -- if self.shot_cooldown<=0 then self.mode=self.fight_modes["shot"] end; -- end self:do_flip(abad) -- self:movement(abad) --if imp.wait==6 then -- imp.wait=0 -- if not imp.enabled then -- imp.counter=imp.counter-1 -- local r = math.random(0,imp.counter-1) -- --print(r) -- if imp.counter==1 or r==1 then -- imp.init() -- end -- return -- end -- -- imp.step=(imp.step+1)%4 -- imp.frame=imp.anim[imp.step+1] -- -- if imp.flip then -- imp.x=imp.x-2 -- if imp.x==78 then -- fireball.init(imp.hab,imp.x+8,imp.y+4,imp.flip) -- sound.play(audio_hit) -- imp.flip=not imp.flip -- elseif imp.x==-12 then -- imp.reset() -- end -- else -- imp.x=imp.x+2 -- if imp.x==4 then -- fireball.init(imp.hab,imp.x+8,imp.y+4,imp.flip) -- sound.play(audio_hit) -- imp.flip=not imp.flip -- elseif imp.x==92 then -- imp.reset() -- end -- end -- --end end function imp:collision() -- comprovar colisio en l'abad if viewp:inside(self.x, self.y, self.w, self.h) then if collision(abad,self) then abad_hurt(1) end end end -- function imp:direccio( actor ) -- -- msg_print(0,0,"direccio",true) -- local check_side = "L" -- -- definir el punts per a comprobar en el mapa -- if self.fight_modes[self.mode]=="away" then -- if actor.x>self.x then -- -- caminar cap "enrere", check costat esq -- check_side = "L" -- else -- -- caminar cap "endavant", check costat dret -- check_side = "R" -- end -- elseif self.fight_modes[self.mode]=="chase" then -- if actor.x>self.x then -- -- caminar cap "endavant", check costat dret -- check_side = "R" -- else -- -- caminar cap "enrere", check costat esq -- check_side = "L" -- end -- end -- -- local step = 1 -- if check_side=="L" then step = -step end -- -- return step -- end