Log In  

Cart #24500 | 2016-07-04 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

CONCEPT:

Castlevania SotN/Zelda II demake. The main focus of the game is the Zelda II-style combat; but also with palace-building scripts that... well... at this point, basically generates pathways to two keys (or enemies that drop them), an item room (that requires one of the keys), a boss room (that requires the other), and an in-palace shop. There's seven "palace chunks" in total, and later I'll be scripting closeoffs for passageways that aren't used.

DESIRED OUTCOME:

A seven-palace romp with progressive/changing enemies, decent assortment of weapons and passive items, enemy drop RNG that on occasion includes some of these weapons and items, to give it more of that SotN replay/uncertainty, a couple of secret areas of some sort?

SPRITING SUNDAY

TL;DR: Okay, I've done a fair portion of the core spriting, and incidentally, worked ahead a little in Music/Mapping Monday.

First row of spriting is the tileset. The "yellow block" includes some probability of generating a locked door (and a key with it, upstream somewhere); the "green blocks" basically take you from one chunk of the area to another.

The rest of the first page is the beginning of a three-layer spriting setup; upper body, lower body, and head (heads will go on page 2). Even though the standing sprites look "full," they're really designed to combine upper and lower body poses for various effects. The lower body relates to movement, while the upper relates to weapon management... so this way, you can still move side to side while executing standing attacks.

Crouching frames, however, are committed to crouch states/attacks. The crouching attack actually gets an ADDITIONAL tile of stretch/range, giving it a little bit of an advantage over standing attacks. This is compensated by making them more vulnerable (partly due to the body stretch) to airborne attacks or downward thrusts. There's also an "up strike" (and upward thrust) in the design to counter air attacks, and a plan of cancelability between them to allow for some comboability. So in a way, it's combining fighting game design with the core gameplay, too.

I also managed to make the subscreen, the top of which (hearts/coins/keys) will likely remain persistent throughout the game... I'm hoping I can make the pause function freeze the "action pane," then scroll it down (revealing the entire subscreen)... and the unpause function scroll it back up and resume. (pointers?)

Heads will be rolling soon (either while wrestling with other parts like the music tracker tomorrow, or next week if this becomes a two-week project). I'm planning on simply changing the colors and assigned heads (and weapons/HP) in a cross-reference kind of table so that a single function can generate an assortment of enemies and attack/defense patterns; like so:

FUNCTION MAKEENEMY(head,color)

head will assign attack/defense priorities (primary and secondary - primary is reactive to a specific player state, secondary is what it does if the player does not enter that state).

color will assign HP and weapon (which will factor up with progression).

The idea is that 12 variants of each will generate 144 creatures, which spread across 7 levels? Each level will have about 20 enemies to pool from, and each playthrough will assign maybe 4 or 5 of them.

I'm also planning on putting a few basic creatures in play as well... some "chunks" are designed for this fighting system (which will focus more on the core enemies), while a few are more focused on the lateral platforming that rounds out the action, which is what the "smaller" creatures are for. But I don't plan on making them so small that you have to crouch-stab everything (or the standing attack's range?).

The thing with the little creatures though, is that since the game is very map intensive, the shared data is going to be map-prioritized... so I've gotta dig through the infamous favorites of the titles and find which ones are most relevant to the game and just make a few of them... but again, after the heads and combat variants are in place. Those are the more important ones.

Well, that's all for today. Tomorrow: Music/Mapping Monday!

It's really just my second time wrestling with the SFX/Music tracker; I'm hoping to compose two alternating palace themes, a boss battle theme, and a "final boss" theme.

P#24501 2016-07-04 01:40 ( Edited 2018-02-11 13:47)

There seems to be a "CARTRIDGE FORMAT ERROR 1"... which is a shame, because what you're describing sounds like fun!

P#24516 2016-07-04 08:23 ( Edited 2016-07-04 12:23)

It has no code yet, right now it's just sprites and maps. And thank you! I'm using the site as a recursive backup until it's in a playable state (which will be announced).

That said... got invited to a July 4th thing, had to work late and go in early tonight... so this may take more days than I was allowing myself. Tomorrow is "Writing Wednesday" (this is where I start the code part; but I still have to mash some heads in to get the basic FSM in place)... and I'll have to come back to Music Monday/Title Screen Tuesday next week.

I'm okay with this being a two-weeker. Even a three-weeker if that's what it takes. Hopefully my CHIP will ship soon! Then I can dev to and from work, and on at least one of my breaks, too. That'll help things a LOT. (And is the other reason I'm keeping recursive backups here!)

P#24679 2016-07-05 23:23 ( Edited 2016-07-06 03:23)

"So where was I again?"

Okay... I'm working on an FSM for the player and humanoid enemies now. I do see how in some projects, a player-based FSM works (mostly through "update()")... but how would I modify this to be on a per-entity basis?

Don't get me wrong, the game's going to have a few basic creature-like things that'll be way simpler, but since the main focus of this is on the dueling, I want to have some universal state control that applies equally between the player and enemies.

Also, going through a checklist of typical states for this sort of thing...

STAND
-idle
-damaged
-attack
-attackup
-block
-walk
-walkattack

CROUCH
-idle
-damaged
-attack
-block
-stun
-dead

JUMP
-upward
-arch
-downward
-damaged (normal)
-popup (hit with up-attack/thrust)
-upthrust
-downthrust
-wing1...wing9 (this is for some special items used to modify jumping)

Finally, a branching pathway generator, to define the parameters of scene usage.

Start...
>Key branch, Item branch (requires key)
>Key branch, Treasure branch (requires key)
>Key branch, Miniboss branch (requires key, awards heart container)
>Key branch, Boss branch (requires key), exit
>Shop branch
>?? Casino branch (a wheel that can modify stats or consumables)
>?? Horde branch
>?? 3-wave Trap branch

Any other room/branch ideas to consider?

P#39145 2017-04-07 08:53 ( Edited 2017-04-07 12:53)

Okay. So 2017 was a DISASTER at my job. Tons of relocations, retirements, and a deliberate effort to minimize restaffing - so bad that my job in that year had more work-related injuries than my ENTIRE JOB HISTORY COMBINED. Which of course, only made that problem WORSE.

Long story short, I've been working on my projects again this week after 5 months of not even touching them. Hence, my lack of forum activity as well.

So I'm in the midst of creating (and animating) my FSM for the game... and I'm kind of hitting a syntax hiccup that I'm not understanding right now. In the attack animations, I want to add windup, so when I enter the state, the attack comes out in 5 frames/steps instead of immediately. Now, I can initiate animations right away, but making it trigger the attack on the correct frame is being dicey.

I guess, more specifically, on frame 5 of attack animations, I want to add a "maketarget()" that is the active weapon. I may go back and make different framerates for different kinds of weapons (for tactical reasons), but for now I'm sticking with simplicity.

Anybody know of some trickery that'll do that?

--concert of the damned
_init()
--globals
maxhp=6
maxwp=6
maxrun=0.4
maxjump=28
shotdmg=5
weapdmg=15
accframes=20 --to max, -2 to decel
jmpframes=40 --up
dshframes=50 --duration
chgframes=50 --buster
fricrate=0.95
maxdrop=8
gravity=1
facing=1 -- -1=l 0=u 1=r
p.st=0
airjump=0
stall=0

screen=0 --title

function shuf(t)
 local r=rnd
 assert (t,"shuf() expects table, got nil")
 local iterations=#t
 local j
 for i=iterations,2,-1 do
  j=rnd(i)
  t(i),t(j)=t(j),t(i)
 end
end

function name(n)
 local nlist={"ace","ard","ang","ent","erg","esk","ilk","ixe","ins","oot","ong","oss","unn","urt","uan","yrt"}
 n1=n/25
    if n1=1 then n1="ch"
    if n1=2 then n1="b"
    if n1=3 then n1="c"
    if n1=4 then n1="d"
    if n1=5 then n1="sh"
    if n1=6 then n1="f"
    if n1=7 then n1="g"
    if n1=8 then n1="h"
    if n1=9 then n1="th"
    if n1=10 then n1="j"
    if n1=11 then n1="k"
    if n1=12 then n1="l"
    if n1=13 then n1="m"
    if n1=14 then n1="n"
    if n1=15 then n1="fl"
    if n1=16 then n1="p"
    if n1=17 then n1="qu"
    if n1=18 then n1="r"
    if n1=19 then n1="s"
    if n1=20 then n1="t"
    if n1=21 then n1="ph"
    if n1=22 then n1="v"
    if n1=23 then n1="w"
    if n1=24 then n1="x"
    if n1=25 then n1="y"
  n2=nlist#n\16
 return (n1,n2)
end

function p_run()
 local aframes=accframes
 local xmove=maxrun
 if (btnp(0)) facing=-1
 if (btnp(1)) facing=1
 if (btn(0)=1 and btn(1)=1)
 then (btn(0),btn(1))=(0,0)
 else
 if btn(0)=1 or btn(1)
 aframes-=1
 else
 if btn(0)=0 and btn(1)=0
 foreach aframes<accframes
 aframes+=2
 end
 for a=1,aframes
  xmove*=fricrate
 end
 if (xmove>maxrun) xmove=maxrun
 player.x+=xmove*facing
end

function p_jump(jh or 0, jf or 0)
 if (jh=0) jh=jumpheight
 if (jf=0) jf=jumpframes
 local px=jh/(jf!)
 for j=-jf,999
  ymove=px*j
  if(ymove>maxdrop)ymove=maxdrop
  j+=1
  if(j>999)j=999
end

function hitwall(_x,_y)
 if (checkspot(p.x,p.y,0)or checkspot(p.x,p.y+7,0) return true
 if (checkspot(p.x+7,p.y,0)or checkspot(p.x+7,p.y+7,0) return true
 return false
end

function hitfloor(_x,_y)
 if (checkspot(p.x,p.y,0)or checkspot(p.x+7,p.y,0)) return true
 if (checkspot(p.x,p.y+7,0)or checkspot(p.x+7,p.y+7,0)) return true
 return false
end

function checkspot(_x,_y,_flag)
 local tilex=flr(_x/8)
 local tiley=flr(_y/8)
 local tile=mget(tilex+levelx,tiley+levely)
 return fget(tile,_flag)
end

function bounce(obj,m,xdir or -1,ydir or -1)
 obj.xmove=m*xdir*2
 obj.ymove=m*ydir
 if hitwall(obj.x,obj.y)=true
 then
 xdir*=-1
 obj.xmove=m*xdir*2
 obj.ymove=m*ydir
 else
 if hitfloor(obj.x,obj.y)=true
 then
 ydir*=-1
 obj.xmove=m*xdir
 obj.ymove=m*ydir*2
end

function movep()
 local oldx=p.x
 local oldy=p.y
 (p.x,p.y)+=(xmove,ymove)
 if (hitwall(p.x,p.y)=true) p.x=oldx
 if (hitfloor(p.x,p.y)=true) p.y=oldy
end

function maketarget(obj,scr,x,y,xrange or 0,yrange or 0,speed or 0,loop or 0)
--x/y position relative to map
 obj.x=((scr\5)*16+x)
 obj.y=((scr/5)*16+y)
--set sine motions to control
 local movex=2*sqrt(xrange)*speed
 local movey=2*sqrt(yrange)*speed
--reverse direction! 
 if (movex=xrange or movex=-xrange or xrange<0) movex*=-1
 if (movey=yrange or movey=-yrange or yrange<0) movey*=-1
--diagonals or curves
 if loop=1 then
  movex=xrange
 elseif loop=-1 then
  movex-=xrange
end

function collide(p,other)
    if
    other.p.x+other.hitbox.x+other.hitbox.w > obj.p.x+obj.hitbox.x and 
    other.p.y+other.hitbox.y+other.hitbox.h > obj.p.y+obj.hitbox.y and
    other.p.x+other.hitbox.x < obj.p.x+obj.hitbox.x+obj.hitbox.w and
    other.p.y+other.hitbox.y < obj.p.y+obj.hitbox.y+obj.hitbox.h 
    then
    return true
    end
end

function topanim(act,f1,f2 or 0,f3 or 0,f4 or 0, f5 or 0, f6 or 0, f7 or 0)
 f=f1
 spr(f,act.x-8,act.y-16,[16,8],f,0)
 if f2=0 then f=f1 else f=f2
 if f3=0 then f=f1 else f=f3
 if f4=0 then f=f1 else f=f4
 if f5=0 then f=f1 else f=f5
 if f6=0 then f=f1 else f=f6
 if f7=0 then f=f1 else f=f7
 if f8=0 then f=f1 else f=f8
 f=f1
end

function botanim(act,f1,f2 or 0,f3 or 0,f4 or 0, f5 or 0, f6 or 0, f7 or 0)
 frame=1
 f=f1
 spr(f,act.x-8,act.y-8,[16,8],f,0)
 if frame=1 then
  f=f1
 elseif frame=2 then
  if f2=0 then f=f1 and frame=1 else f=f2
 elseif frame=3 then
  if f3=0 then f=f1 and frame=1 else f=f3
 elseif frame=4 then
  if f4=0 then f=f1 and frame=1 else f=f4
 elseif frame=5 then
  if f5=0 then f=f1 and frame=1 else f=f5
 elseif frame=6 then
  if f6=0 then f=f1 and frame=1 else f=f6
 elseif frame=7 then
  if f7=0 then f=f1 and frame=1 else f=f7
 elseif frame=8 then
  if f8=0 then f=f1 and frame=1 else f=f8
 frame+=1
 if frame>8 then frame=1
end

function head()
 //standing/aerial sprites only
 spr(act.head,act.x-4,act.y-24,[8,8],f,0)
end

 function state(act,st)
 if facing=-1 then f=1 else f=0
 if act.st=0 then
 elseif act.st=1 then
  //display cursor
 elseif act.st=2 then
  //stand
  topanim(act,16)
  botanim(act,32)
  head()
 elseif act.st=3 then
  //move l/r on ground
  topanim(act,16)
  botanim(act,34,34,36,36,38,38)
  head()
  p_run()
 elseif act.st=4 then
  //jump up~air
  topanim(act,20)
  botanim(act,42)
  head()
  if airjump>0 or checkspot(x,y+1,solid)=true
  then p_jump() and p_run()
  else p_run()
 elseif act.st=5 then
  //jump down~air
  topanim(act,20)
  botanim(act,44)
  head()
 elseif act.st=6 then
  //block~high
  topanim(act,16)
  botanim(act,32)
  head()
 elseif act.st=7 then
  //block~low
  botanim(act,48)
  spr(head,act.x-4,act.y-16,[8,8],f,0)
 elseif act.st=8 then
  //elevator up
 elseif act.st=9 then
  //elevator down
 elseif act.st=10 then
  //ai lateral
 elseif act.st=11 then
  //recover to neutral
  botanim(act,56,56)
  spr(head,act.x-4,act.y-16,[8,8],f,0)
 elseif act.st=12 then
  //stand attack
   topanim(act,20,20,20,22,22,22)
   botanim(act,32)
   head()
 elseif act.st=13 then
  //uppercut
   topanim(act,16,16,16,16,26,26,26)
   botanim(act,32)
   head()
 elseif act.st=14 then
  //air attack
   topanim(act,20,20,20,22,22,22)
   botanim(act,36,36,36,42,42,42)
 elseif act.st=15 then
  //crouch attack
   botanim(act,48,48,48,50,50,50)
   spr(head,act.x-4,act.y-16,[8,8],f,0)
   if f=1 then spr(52,act.x-8.act.y-8,[8,8],1,0)
   else spr(52,act.x+16,act.y-8,[8,8],0,1)
 elseif act.st=16 then
  //up thrust
   topanim(act,16,26,26,26,26,28,28,28)
   botanim(act,38,42,42,42,42,44,44,44)
   head()
 elseif act.st=17 then
  //down thrust
   botanim(act,56)
   spr(head,act.x-4,act.y-16,[8,8],f,0)
 elseif act.st=18 then
  //bow charge
 elseif act.st=19 then
  //bow release
 elseif act.st=20 then
  //downed~to recover
   botamin(act,54,54,54)
   //add head/spr 53
 elseif act.st=21 then
  //stand-hit react
   topanim(act,24,24,24,24)
   botanim(act,40,40,40,40)
   head()
   stall=4
 elseif act.st=22 then
  //uppercut react
   topanim(act,24,24,24,24)
   botanim(act,40,40,40,40)
   head()
   stall=7
 elseif act.st=23 then
  //air-hit react
   topanim(act,24,24,24,24)
   botanim(act,40,40,40,40)
   head()
   stall=4
 elseif act.st=24 then
  //crouch hit react
   botanim(act,56,56,56,56)
   spr(head,act.x-4,act.y-16,[8,8],f,0)
   stall=4
 elseif act.st=25 then
  //recovery~left
 elseif act.st=26 then
  //recovery~right
 elseif act.st=27 then
  //bow~up
 elseif act.st=28 then
  //bow~down
 elseif act.st=29 then
  //reserved
 elseif act.st=30 then
  //ai tactic a
 elseif act.st=31 then
  //ai tactic b
 elseif act.st=32 then
  //ai tactic c
 elseif act.st=33 then
  //ai tactic d
 elseif act.st=34 then
  //ai tactic e
 elseif act.st=35 then
  //ai tactic f
 elseif act.st=36 then
  //ai tactic g
 elseif act.st=37 then
  //ai tactic h
 elseif act.st=38 then
  //ai tactic i
 elseif act.st=39 then
  //ai tactic j
end

end --of _init()
_update()

end --of _update()
_draw()

end --of _draw()
P#49161 2018-02-11 08:47 ( Edited 2018-02-11 13:50)

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2022-08-08 01:32:48 | 0.009s | Q:17