Author Topic: Still stuck with Reimu Player.  (Read 4842 times)

Drake

  • *
Still stuck with Reimu Player.
« on: July 30, 2009, 03:45:23 AM »
Just so it might get a bit more attention.

As some of you know I've been working on and off on a player character. But not just any player character, a Reimu player designed to act like one of ZUN's. Such things include the focusing circle, visible hitbox overtop of most bullets, dynamic options and detailed animated sprites. Such things are much harder than I originally thought and required many workarounds to incorporate.

Up to now I've been able to pretty much figure everything out. There are more details that I should probably be able to finish by myself, but I've hit a snag: animated bullets. I mean, of course you can animate a bullet through the PlayerShotData script, but I mean what happens when a bullet strikes an enemy. If you pull up MoF, SA or UFO and look at the bullets, you can see that they are indeed animated. Now, I can animate the bullets, that much was easy. The problem here lies in the enemy collision detection; there is the declaration for their hitbox, detection of object horizontal intersection, and you can call if the enemy was damaged for that one sound to start playing, but there is currently no method to detect bullet-enemy collision.

The farthest I have gotten is creating an object surrounding the enemy and using Obj_Obj_Collision. The bullets are animated more or less how I want, but I cannot for the life of me figure out how I can reference two different objects in one !Obj_BeDeleted loop.

Here is what I have. pl00.txt is the working version I have so far. pl01.txt is the experimental version I'm constantly changing trying to figure this thing out. Check them both out, if you could. ReimuD2 obviously doesn't work.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Zengar Zombolt

  • Space-Time Tuning Circle - Wd/Fr
  • Green-Red Divine Clock
Re: Still stuck with Reimu Player.
« Reply #1 on: July 30, 2009, 04:04:40 AM »
Tested it on OnTheNet's Eirin boss script.
There is an animation when the needles dissappear, the thing is that they dissappear very far from the boss, thus, they don't hit at all. Also, there's this white blob over the enemy that's covering her right half, and enlarges itself upon your death.
And well, besides that, I can't see anything else wrong.

Drake

  • *
Re: Still stuck with Reimu Player.
« Reply #2 on: July 30, 2009, 04:45:27 AM »
Well lol that's the problem silly, did you read my post

The giant blob is the object laser I'm using as a target for collision detection. I will make it invisible and completely cover the enemy once I know it works. Currently I have the bullets check for intersection just to confirm that it does indeed animate and disappear, which is why they disappear so soon.

I forgot to mention, the damage output is a complication from the collision problem. If the bullet disappears upon hitting the enemy, it won't animate, so I had to set the penetrate to 10 or something. Also, because the damage the option bullets generate is reduced to zero when being animated, the option bullets themselves do minimal damage. Most of the damage produced right now is from the main shot. Of course, once the collision problem is fixed I'll regulate the damage.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Stuffman

  • *
  • We're having a ball!
Re: Still stuck with Reimu Player.
« Reply #3 on: July 30, 2009, 03:25:35 PM »
Code: [Select]
task fancybullet(){
  let bulletx=bullet start position;
  let bullety=bullet start position;
  blah blah make object;
  while(!objbedeleted){
    bulletx=obj_getx(obj);
    bullety=obj_gety(obj);
    blah blah bullet code;
  }
  make effect object @ bulletx,bullety;
  while(!objbedeleted and is animating or whatever){
    blah blah animation code;
  }
}

?

Drake

  • *
Re: Still stuck with Reimu Player.
« Reply #4 on: July 30, 2009, 07:20:18 PM »
You gave me an idea and now I'm not so much stuck as I am confused.

Code: [Select]
#TouhouDanmakufu[Player]
#ScriptVersion[2]
#Menu[Reimu D3]
#Text[Hakurei Reimu type D
            ?uConcentrated attack type?v

Shot:   ?uAbsolution Needle?v

Bomb: ?uWild Annihilation Dance?v]
#Image[.\sl_pl00.png]
#ReplayName[ReimuD3]

script_player_main{

#include_function ".\common.txt"
let c = GetCurrentScriptDirectory();
let bNextShot = false;
let optiona = 0;
let focusalpha = 0;
let focussize = 1;
let drawcount = 0;
let shotcount = -1;
let rad = 45;

task DrawHitbox(){
let hitbox = Obj_Create(OBJ_SHOT);
Obj_SetSpeed(hitbox,0);
Obj_SetCollisionToPlayer(hitbox, false);
ObjShot_SetBombResist(hitbox, true);
ObjShot_SetGraphic(hitbox, 100);
while(!Obj_BeDeleted(hitbox)){

if(IsPressRight()==true){
if(IsPressDown()==true){ Obj_SetPosition(hitbox, GetPlayerX+1, GetPlayerY+1); //Right+Down
}else if(IsPressUp()==true){ Obj_SetPosition(hitbox, GetPlayerX+1, GetPlayerY-2); //Right+Up
}else{ Obj_SetPosition(hitbox, GetPlayerX+1, GetPlayerY);} //Right

}else if(IsPressLeft()==true){
if(IsPressDown()==true){ Obj_SetPosition(hitbox, GetPlayerX-2, GetPlayerY+1); //Left+Down
}else if(IsPressUp()==true){ Obj_SetPosition(hitbox, GetPlayerX-2, GetPlayerY-2); //Left+Up
}else{ Obj_SetPosition(hitbox, GetPlayerX-2, GetPlayerY);} //Left

}else if(IsPressDown()==true){ Obj_SetPosition(hitbox, GetPlayerX, GetPlayerY+1); //Down

}else if(IsPressUp()==true){ Obj_SetPosition(hitbox, GetPlayerX, GetPlayerY-2); //Up

}else{ Obj_SetPosition(hitbox, GetPlayerX, GetPlayerY); //Neutral
}
Obj_SetAngle(hitbox, optiona);
Obj_SetAlpha(hitbox, focusalpha);
yield;
}
}

task OptionScript{
if(IsPressShot()==true && shotcount==-1){shotcount=0;}
if(IsPressSlow()==true){rad = 20;}else{rad = 45;}
if(shotcount%5 == 0){
PlaySE(c~"se_plst00.wav");
let r = rand(-5,5);
ShotScript(GetPlayerX+8, GetPlayerY-10, GetPlayerX+(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)), r, true);
r = rand(-5,5);
ShotScript(GetPlayerX-8, GetPlayerY-10, GetPlayerX+(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)), r, true);
r = rand(-5,5);
ShotScript(0, 0, GetPlayerX-(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)), r, false);
r = rand(-5,5);
ShotScript(0, 0, GetPlayerX-(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)), r, false);
}
if(shotcount>=0){shotcount++;}
if(shotcount>=5){shotcount=-1;}
yield;
}

task ShotScript(x1,y1,x2,y2,r,m){
//OPTION BULLET
let g = 101;
let i = -2;
let a = 170;
let optiony = y2;
let opt = Obj_Create(OBJ_SHOT);
Obj_SetPosition(opt, x2, y2);
Obj_SetAngle(opt, 270);
ObjShot_SetGraphic(opt, g);
Obj_SetAlpha(opt, a);
Obj_SetSpeed(opt, 10);
ObjShot_SetBombResist(opt, true);
ObjShot_SetDamage(opt, 0.7);
ObjShot_SetPenetration(opt, 10);
while(!Obj_BeDeleted(opt)){
optiony = Obj_GetY(opt);
let targety = GetEnemyY+16;
if(Obj_IsIntersected(opt)==true && optiony<targety){
i = 0;
a = 220;
Obj_SetAngle(opt, 270+r);
//SetX(50);
}else{
g = 101;
}
if(i>=0){
ObjShot_SetDamage(opt, 0);
Obj_SetSpeed(opt, 1.5);
i++;
g = 102;
a-=2;
}
if(i>16){
Obj_Delete(opt);
}
ObjShot_SetGraphic(opt, g);
Obj_SetAlpha(opt, a);
yield;
}

//MAIN BULLET
if(m==true){
let g = 103;
let i = -2;
let a = 115;
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, x1, y1);
Obj_SetAngle(obj, 270);
ObjShot_SetGraphic(obj, g);
Obj_SetAlpha(obj, a);
Obj_SetSpeed(obj, 10);
ObjShot_SetBombResist(obj, true);
ObjShot_SetDamage(obj, 1);
ObjShot_SetPenetration(obj, 10);
Obj_SetCollisionToObject(obj, true);
while(!Obj_BeDeleted(obj)){
if(Collision_Obj_Obj(obj,obj)==true){
i = 0;
}else{
g = 103;
}
if(i>=0){
ObjShot_SetDamage(obj, 0);
i++;
a-=3;
}
if(i>=0 && i<6){
g = 104;
Obj_SetSpeed(obj, 1.5);
}else if(i>=6 && i<12){
a = 35;
g = 105;
Obj_SetSpeed(obj, 1.5);
}else if(i>16){
Obj_Delete(obj);
}
ObjShot_SetGraphic(obj, g);
Obj_SetAlpha(obj, a);
yield;
}
          }
}

@Initialize{
LoadGraphic(c~"pl00.png");
LoadPlayerShotData(c~"plshot00.txt");
                                          SetPlayerLifeImage(c~"pl00.png", 213, 293, 247, 325);
SetRibirthFrame(15);
SetSpeed(4, 1.5);
DrawHitbox;
}

@MainLoop{
drawcount++;
SetIntersectionCircle(GetPlayerX, GetPlayerY, 1);
optiona+=3; if(optiona>=360){optiona = 0;}

/*TARGET
ascent(enemy in EnumEnemyBegin..EnumEnemyEnd){
let enemyID = EnumEnemyGetID(enemy);
let target = GetEnemyInfo(enemyID, ENEMY_Y) + 16;
}*/
OptionScript;
yield;
}
@Missed{}
@SpellCard{
SetSpeed(4, 1.5);
UseSpellCard("WildAnnihilationDance", 0);
}
@DrawLoop{
SetTexture(c~"pl00.png");
SetAlpha(255);
SetGraphicScale(1,1);

//Draw player
SetGraphicAngle(0,0,0);
if(IsPressRight()==true){
SetGraphicRect(228, 102, 260, 146);
}else if(IsPressLeft()==true){
SetGraphicRect(230, 53, 261, 97);
}else{
if(drawcount<10){SetGraphicRect(5, 3, 38, 51);}
if(drawcount>=10 && drawcount<20){SetGraphicRect(37, 3, 70, 51);}
if(drawcount>=20 && drawcount<30){SetGraphicRect(69, 3, 102, 51);}
if(drawcount>=30 && drawcount<40){SetGraphicRect(101, 3, 134, 51);}
if(drawcount>=40 && drawcount<50){SetGraphicRect(134, 3, 165, 51);}
if(drawcount>=50 && drawcount<60){SetGraphicRect(165, 3, 198, 51);}
if(drawcount>=60 && drawcount<70){SetGraphicRect(198, 3, 229, 51);}
if(drawcount>=70 && drawcount<80){SetGraphicRect(228, 3, 262, 51);}
}
DrawGraphic(GetPlayerX, GetPlayerY);

//Draw options
SetGraphicRect(70, 148, 84, 162);
SetGraphicAngle(0,0,optiona*-1);

DrawGraphic(GetPlayerX+(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)));
DrawGraphic(GetPlayerX+(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)));
DrawGraphic(GetPlayerX-(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)));
DrawGraphic(GetPlayerX-(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)));

//Draw focus circle
if(IsPressSlow==true){
focusalpha+=30;
if(focusalpha>250){focusalpha=250;}
}else{
focusalpha-=30;
if(focusalpha<0){focusalpha=0;}
}
if(focusalpha>210){
focussize-=0.04;
if(focussize<=1){focussize=1;}
}else{
focussize = (focusalpha/240)+0.4;
}
SetAlpha(focusalpha);
SetGraphicRect(213, 151, 285, 213);
SetGraphicScale(focussize, focussize);
SetGraphicAngle(0,0,0);
DrawGraphic(GetPlayerX, GetPlayerY);
/*SetGraphicScale(1,1);
SetGraphicAngle(0,0,optiona);
DrawGraphic(GetPlayerX, GetPlayerY);*/

drawcount++;
if(drawcount>=80){drawcount=0;}
}

@Finalize{}
}

script_spell WildAnnihilationDance{
let frame = 0;
@Initialize{
SetPlayerInvincibility(120);
DeleteEnemyShotToItem(SHOT);
CollectItems;
}
@MainLoop{
frame++;
if(frame>120){End;}
yield;
}
@Finalize{
}
}

It kind of works. Testing it on Eirin, what happens is that on some points, mostly to the side of Eirin, the animation happens pretty much like I want it to. However, most of the bullets that hit her disappear before they even get close to her, so no animation. If you run up to her (with invincibility), they start happening more often until Reimu is level with targety. But if I change targety, sometimes it doesn't even change. There is no difference between GetEnemyY+200 and 300, and there are all sorts of weird stuff that happens when you get closer or farther. Experimenting with it doesn't really tell me anything right now.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Infy♫

  • Demonic★Moe
  • *
Re: Still stuck with Reimu Player.
« Reply #5 on: August 03, 2009, 03:11:29 PM »
so i had an idea of making an object bullet with low penetration.
as soon as it gets destroyed, it summons a new bullet of the same type.
the parent starts with a variable equal to 0 but as a new bullet is created this var increases until it reaches a limit. after that new bullets will not be created. based on the value of this variable, a frame for an animation is chosen