Oh, Sorry my English is not clear?
I want to connect two objects (like for example GetObjectDistance(obj1,obj2) ), but both objects are in different loop making rings. With SetCommonData (as you said before) I have no imagination how could I do that.
let listA = [];
let listB = [];
// note that this is specifically a function, which creates and sets up a single object we want
function ObjectA(y){
// create and initialize the object
let objA = CreateShotA1(20, y, 1, 25, DS_BALL_S_RED, 20);
// task *within* a function, which keeps running even when the function returns
task DoStuffA(){
// running loop
while(!Obj_IsDeleted(objA)){
// in this example, A bullets change color when they collide with B bullets
let collision = false;
ascent(i in 0..length(listB)){
if(GetObjectDistance(objA, listB[i]) < 20){
ObjShot_SetGraphic(objA, DS_BALL_S_BLUE);
collision = true;
break;
}
}
if(!collision){
ObjShot_SetGraphic(objA, DS_BALL_S_RED);
}
yield;
}
}
// run the above task
DoStuffA();
// return the object ID you just created to store it in a variable with higher scope
return objA;
}
// similar to above
function ObjectB(y){
let objB = CreateShotA1(364, y, 1, 155, DS_BALL_S_RED, 20);
task DoStuffB(){
while(!Obj_IsDeleted(objB)){
let collision = false;
ascent(i in 0..length(listA)){
if(GetObjectDistance(objB, listA[i]) < 20){
ObjShot_SetGraphic(objB, DS_BALL_S_BLUE);
collision = true;
break;
}
}
if(!collision){
ObjShot_SetGraphic(objB, DS_BALL_S_RED);
}
yield;
}
}
DoStuffB();
return objB;
}
ascent(i in 0..10){
listA = listA ~ [ ObjectA(20+i*20) ]; // creates ten of the ObjectA bullets
listB = listB ~ [ ObjectB(20+i*20) ]; // creates ten of the ObjectB bullets
loop(10){yield;}
}
I was waiting for an elaboration because I'm pretty sure my last post needed a concrete example.Code: [Select]let listA = [];
let listB = [];
function ObjectA(y){
let objA = CreateShotA1(20, y, 1, 25, DS_BALL_S_RED, 20);
task DoStuffA(){
while(!Obj_IsDeleted(objA)){
let collision = false;
ascent(i in 0..length(listB)){
if(GetObjectDistance(objA, listB[i]) < 20){
ObjShot_SetGraphic(objA, DS_BALL_S_BLUE);
collision = true;
break;
}
}
if(!collision){
ObjShot_SetGraphic(objA, DS_BALL_S_RED);
}
yield;
}
}
DoStuffA();
return objA;
}
function ObjectB(y){
let objB = CreateShotA1(364, y, 1, 155, DS_BALL_S_RED, 20);
task DoStuffB(){
while(!Obj_IsDeleted(objB)){
let collision = false;
ascent(i in 0..length(listA)){
if(GetObjectDistance(objB, listA[i]) < 20){
ObjShot_SetGraphic(objB, DS_BALL_S_BLUE);
collision = true;
break;
}
}
if(!collision){
ObjShot_SetGraphic(objB, DS_BALL_S_RED);
}
yield;
}
}
DoStuffB();
return objB;
}
ascent(i in 0..10){
listA = listA ~ [ ObjectA(20+i*20) ]; // creates ten of the ObjectA bullets
listB = listB ~ [ ObjectB(20+i*20) ]; // creates ten of the ObjectB bullets
loop(10){yield;}
}
There are better ways to code this particular example, but hopefully this illustrates my previous post. Note that both A objects and B objects are created in different function scopes and have different behaviour, but still reference each other. The functions that create the objects return their IDs, so you can store the object IDs using variables declared in higher scopes (so they're more accessible). The tasks within each function still run independently of each other, even though the function surrounding it returns.
2 questions.
1. How to do a magic circle (the circles that spin around the boss)
2. How to spawn familiars
task BulletCommandExplosions(shot){
let rx = ObjMove_GetX(shot);
let ry = ObjMove_GetY(shot);
let angleR = rand(0, 360);
while(rx > 0 && rx < GetStgFrameWidth){yield;}
if(rx <= 0){
loop(12){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
ObjShot_SetDeleteFrame(shot, 0);
angleR += 360/12;}
}
if(rx >= GetStgFrameWidth){
loop(12){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
ObjShot_SetDeleteFrame(shot, 0);
angleR += 360/12;}
}
}
However, the bullets exploded instantly after being spawned. So, why didn't it work? It was a mistake to put while(rx > 0 && rx < GetStgFrameWidth){yield;} so far in the task. I just needed to put it one line after the task is declared, and it started to work!task BulletCommandExplosionsSide(shot){
while(ObjMove_GetX(shot) > 20 && ObjMove_GetX(shot) < GetStgFrameWidth-20){yield;}
// Replace Width with Height and GetX with GetY if you want it to explode if it touches the upper and lower screen instead of the sides.
let rx = ObjMove_GetX(shot);
let ry = ObjMove_GetY(shot);
let angleR = rand(0,360);
if(rx <= 20&&!Obj_IsDeleted(shot)){
// Replace rx with ry if you want it to explode if it touches the upper and the lower screen instead of the sides.
loop(14){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 5);
ObjShot_SetDeleteFrame(shot, 5);
angleR += 360/14;}
}
if(rx >= GetStgFrameWidth-20&&!Obj_IsDeleted(shot)){
// Replace Width with Height if you want it to explode if it touches the upper and the lower screen instead of the sides.
loop(14){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 5);
ObjShot_SetDeleteFrame(shot, 5);
angleR += 360/14;}
}
}
And just wanted to point out, the "3" in the thread title is in Arabic, while the "II" in the old was in Greek. Just a meaningless observation.How do you make bullets fire not in a ring, but in a square?
Thanks!
But how would you shoot it? Can I have a code example from an actual script?
(Wow, I need to brush up on my advanced math skills)
function CreateShotShapeOA1(obj, sides, gap, speed, angle_off, graphic, delay){
let x = ObjMove_GetX(obj);
let y = ObjMove_GetY(obj);
let t = 0;
while(t < 360){
let r = cos(180/sides) / cos(((t - angle_off) % (360/sides)) - (180/sides));
CreateShotA1(x, y, r * speed, t, graphic, delay);
t += gap;
}
}
CreateShotA1(x + size*r*cos(t), y + size*r*sin(t), s, a, g, d);
No, either way is fine, and I was actually specifically looking at shooting the shape outwards. Because this is already done in polar coordinates, it uses an angle (which you're already going to loop through just as though you were shooting a circle), and a "radius", which is given by the above equation. Like I wrote in the last post, you can interpret this radius as a speed and just plug it in, multiplying it for a faster shape. Basically "increase the radius of the shape by speed each frame".Code: [Select]function CreateShotShapeOA1(obj, sides, gap, speed, angle_off, graphic, delay){
let x = ObjMove_GetX(obj);
let y = ObjMove_GetY(obj);
let t = 0;
while(t < 360){
let r = cos(180/sides) / cos(((t - angle_off) % (360/sides)) - (180/sides));
CreateShotA1(x, y, r * speed, t, graphic, delay);
t += gap;
}
}
Meanwhile spawning the shape at a location and size is also a matter of multiplying ("give the shape a certain radius size") and converting back to x,y coordinates, soCode: [Select]CreateShotA1(x + size*r*cos(t), y + size*r*sin(t), s, a, g, d);
How can I modify an object with a laser (ex. if a bullet is close to a laser, the bullet is destroyed)?
Thanks :D And homing bullets? How do they work?Please define though for which purpose you want to use them. Do the bullets home accurately (like Reimu's homing amulets) or only upon firing (so the player can graze them). The latter is achieved by calculating the angle between the object bullet and player using: GetAngleToPlayer(obj); or if you're happy with manual labour using: atan2(y1-y2,x1-x2); when setting the angle of the object bullet. Where x/y positions of the object + player is filled in.
let dir = GetAngleToPlayer(obj);
ObjMove_SetAngle(obj,dir);
or
let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
ObjMove_SetAngle(obj,dir);
case(EV_PLAYER_SHOOTDOWN){//To disable continue system, block comment this case.
if(GetPlayerLife<0){
SetPlayerLife(0.123); //from Arby26
ContinueSystem;
}
}
By setting the player life to be above 0, you prevent the script from ending. My Continue System task handles communication with the package - if the player has continues left and it's not a replay, the package is notified to Pause the Stage. From here, the player decides in the package which course they would like to take, and the stage is notified from the package via NotifyEvent.
I want the homing bullets like Reimu?s ones, but less accurate.
loop{
let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
ObjMove_SetAngle(obj,dir);
yield;
}
loop{
let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
ObjMove_SetAngle(obj,dir);
loop(n){yield;} // where n is a variable
}
loop{
let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
ObjMove_SetAngle(obj,dir+rand(-1,1));
yield;
}
task homing_test{
let obj = CreateShotA1(192, 150, 4, 90, 77, 20);
let speed = 4;
let a = 90;
let a_spd = 5; // rate of angle change
while(!Obj_IsDeleted(obj)){
let angle_to = GetAngleToPlayer(obj);
// choose to increase or decrease angle depending on which is closer
let da = [a_spd, -a_spd][((a - angle_to) % 360) < 180];
// if the angles are close enough, just snap instead
if( (|a - angle_to|) < a_spd){
a = angle_to;
}else{
a = (a + da) % 360;
}
ObjMove_SetAngle(obj, a);
// optionally scale speed so it slows down to adjust angle
let scale = (|(a - angle_to) % 360 - 180|) / 180; // ranges [0,1]; is 1 when angles are equal
ObjMove_SetSpeed(obj, speed * scale^2); // squaring also optional, increases slowdown
yield;
}
}
By setting the player life to be above 0, you prevent the script from ending. My Continue System task handles communication with the package - if the player has continues left and it's not a replay, the package is notified to Pause the Stage. From here, the player decides in the package which course they would like to take, and the stage is notified from the package via NotifyEvent.Oh I see. That is quite a clever workaround. Because 0 lives in Touhou actually means it is your last life right? So preventing it from going to -1? Events are strong it seems, guess I have to call in its help again.
Oh I see. That is quite a clever workaround. Because 0 lives in Touhou actually means it is your last life right? So preventing it from going to -1? Events are strong it seems, guess I have to call in its help again.
Any side effects of keeping never triggering the PlayerState or StageSceneState to PLAYER_DOWN? Like replays breaking. Desyncing, etc.
What are the easiest Touhou bosses to replicate, or base on, in Danmakufu?
What are the easiest Touhou bosses to replicate, or base on, in Danmakufu?
Depends on what you mean by 'base on' or 'replicate', as well as the general availability of graphical assets. This question is extremely broad, but characters with simpler danmaku (Stage 1-2 bosses) without custom graphics (IE not Nazrin) tend to be less of a logistical hassle. It is for this reason that Rumia used to be one of the most commonly used bosses in early scripts.
Cirno.
Just follow Helepolis tutorial. Very easy xD
...At this rate, I'm going to recreate the entire EoSD...If you're aiming to practice making patterns, EoSD is honestly a good game to replicate patterns from. The majority of bullet patterns in EoSD are relatively basic, probably due to ZUN's relative inexperience in pattern making. The only big part that really comes to mind as difficult to replicate would be Sakuya's spellcards, as those rely on a mechanic that's by default absent from Danmakufu Ph3: the time stop. A few other hard ones like Kagome Kagome, Laevateinn, and maybe Royal Flare come to mind, but they aren't very numerous and limited mostly to the extra stage.
But can't you simulate time stop by stopping the pellets / knives and using SetPlayerSpeed(0, 0);, and if possible get the player speed before "stopping time"?
Well, you're both pointing out the problem and the answer slightly yourself :V
You're using a regular render function to mutate a 3D sprite object. The coordinates of a 3D sprite are based on the XYZ of the danmakufu 3D space and the 2D sprites are based on the game field, except when you set the Layer 80+ (or 0.8 if you're using the regular one), which then the entire window of the program become the coordinates. To clarify:
Let us say your game field is X: 200 and Y: 400. You decide to centre your boss using your own GetCenterX / GetCenterY code (Which is field / 2). The boss X,Y position is 100,200. Imagine we try to draw a texture/sprite on Layer 80 using the same functions. We have to keep in mind that our Danmakufu window is by default 640x480. Drawing our texture and giving the GetCenterX/Y will put it at 320,240. Because after all, that is the centre of the whole window. Obviously this won't align with the boss, as they are calculating their coordinates differently. But what if we put our texture on Layer 30? Suddenly, it will align proper, as both are calculating the centre based on the play field.
The same story goes for 3D, except more complicated when you're involving the camera. First of all, 3D coordinates of danmakufu are fixed. If you put something at 0,0,0 in 3D space and you put your camera -256 on the X-axis, your sprite will be off-centre for you, but in terms of code it is still located 0,0,0.
TL DR: You don't want to mix 2D ad 3D to align things because generally it will be a hassle regardless.
Is it an aesthetic thing you wish to put your magic circle in 3D? The 2D sprite allows X Y Z angling as well. Or you think that looks a bit too "thin paper"?
Edit note: explaining more added to original post.
3D Sprite objects are essentially made for background use (as should be obvious now). There shouldn't really be any difference between rotating a 2D Sprite object and a 3D one as far as I'm aware; is there a reason you switched when you could spin around the previous one just the same? As it is you might also get background interference/clipping.
How do you put quotation marks inside strings?
let name = "Something Sign \"Something Something\"";
How do you put quotation marks inside strings?
How do you put quotation marks inside strings?Simply typing this inside a string also works:
"
How much damage should a player do? I mean for the most used shot types.
function MagicCircle(x, y){
let eff = CSD ~ "// Image Folder.";
let spin = 0;
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj, eff);
ObjSprite2D_SetSourceRect(obj, 0,255,255,292);
ObjSprite2D_SetDestRect(obj, 0,0,256,45);
Obj_SetRenderPriorityI(obj, 21);
ObjRender_SetX(obj, x);
ObjRender_SetY(obj, y);
ObjRender_SetScaleXYZ(obj, 1, 1, 0);
ObjRender_SetAngleXYZ(obj, 0, 0, spin);
}
task MagicCircle(){ // note `task` and no params needed
let eff = CSD ~ "// Image Folder.";
let spin = 0;
let objEnemy = GetEnemyBossObjectID()[0]; // if you've defined the boss' object ID globally already you don't need this
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
// the other setup
while(!Obj_IsDeleted(objEnemy)){ // update loop runs until enemy object is deleted
ObjRender_SetPosition(obj, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 0);
ObjRender_SetAngleXYZ(obj, 0, 0, spin);
spin++;
yield; // stops this task from running until next frame
}
}
while(Obj_IsDeleted(obj)) -> results in: while(false) -> Conclusion: Immediate exit loop.
while(!Obj_IsDeleted(obj)) -> results in: while(!false) -> Because of exclamation mark, the result is reversed -> becomes: while(true) -> Conclusion: keep looping.
while(Obj_IsDeleted(obj) == false) -> results in: while(false == false) which is 'true' -> while(true) -> Conclusion: Continue looping.
It is perfectly legal, but people don't use it for tons of reasons. Not going to go into a debate of 'How To Write Clean Code'.
#include "script/"scriptname"/commonLoad.txt"
"script/"scriptname"/data/boss/N1"
Im trying to #include some stuff :Code: [Select]#include "script/"scriptname"/commonLoad.txt"
But the script that I want to include this library is inside a different folder:Code: [Select]"script/"scriptname"/data/boss/N1"
I usually fix it using an absolute path, but now I want to change the script name folder. Can someone help me?
Also, how often do you carry out (perform, do, make... ) the RaNGE contest?There is no specific description, rule or guideline to make one or when to make one. Occasionally, someone comes up with a good idea + contest rules + judges and present it to the community. If the community shows enough attention, I will sticky it and magically call it a contest on RikaNitori.
Ok it works now. Thanks.
Also, how often do you carry out (perform, do, make... ) the RaNGE contest?
That tutorial won't work if you're using ph3. I recommend you to look inside other script players and learn how do they work. I believe that there aren't player script ph3 tutorials actually.
let bool = true;
while(bool==true){
ObjText_SetText(textBonus, ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE));
yield;
}
while(bool==false){
ObjText_SetText(textBonus, "Failed");
yield;
}
while(ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SHOOTDOWN_COUNT)
+ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SPELL_COUNT) >= 1){
bool=false;
}
Hello again! I have two questions, regarding the spell card bonus counter.
(http://i.imgur.com/5xh7SAn.png)Code: [Select]let bool = true;
while(bool==true){
ObjText_SetText(textBonus, ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE));
yield;
}
while(bool==false){
ObjText_SetText(textBonus, "Failed");
yield;
}
while((ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SHOOTDOWN_COUNT)
+ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SPELL_COUNT)) >= 1){
bool=false;
}
1. How can I make those useless zeros disappear? (The original spell bonus is 2400000 if that's relevant.)
2. For some reason, I can't get "Failed" to show up when the player bombs or misses. Any reasons why?
let bonusget = true;
let bonus = ObjEnemyBossScene_GetInfo(objScene,INFO_SPELL_SCORE);
while(bonusget) {
bonusget = (ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SHOOTDOWN_COUNT)
+ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SPELL_COUNT)) == 0;
bonus = ObjEnemyBossScene_GetInfo(objScene,INFO_SPELL_SCORE);
ObjText_SetText(textBonus, IntToString(bonus));
yield;
}
ObjText_SetText(textBonus, "Failed");
help me pleeease :V
...
Anything should I do to fix this?
Hello you gyus
I'm struggling so much
help me pleeease :V
Anything should I do to fix this?
IIRC, it's the problem with Ultima's Reimu player, not the script itself. Better wait for him to fix it. xDWhaaaaa :V
task renderPlayer{
ObjPrim_SetTexture(playerObj, playerSprite);
Obj_SetRenderPriority(playerObj, 31);
ObjRender_SetBlendType(playerObj,BLEND_ALPHA);
ObjRender_SetAngleXYZ(playerObj, 0,0,0);
ObjRender_SetScaleXYZ(playerObj, 1, 1, 0);
ObjRender_SetAlpha(playerObj, 255);
ObjSprite2D_SetSourceRect(playerObj, 0,0,32,32);
ObjSprite2D_SetDestCenter(playerObj);
//ObjSprite2D_SetDestRect(playerObj,-16,-16,16,16); this didn't work either
ObjRender_SetPosition(playerObj,GetPlayerX,GetPlayerY,0);
while(!Obj_IsDeleted(playerObj)){
ObjRender_SetPosition(playerObj,GetPlayerX,GetPlayerY,0);
yield;
}
}
Code: [Select]task renderPlayer{
ObjPrim_SetTexture(playerObj, playerSprite);
Obj_SetRenderPriority(playerObj, 31);
ObjRender_SetBlendType(playerObj,BLEND_ALPHA);
ObjRender_SetAngleXYZ(playerObj, 0,0,0);
ObjRender_SetScaleXYZ(playerObj, 1, 1, 0);
ObjRender_SetAlpha(playerObj, 255);
ObjSprite2D_SetSourceRect(playerObj, 0,0,32,32);
ObjSprite2D_SetDestCenter(playerObj);
//ObjSprite2D_SetDestRect(playerObj,-16,-16,16,16); this didn't work either
ObjRender_SetPosition(playerObj,GetPlayerX,GetPlayerY,0);
while(!Obj_IsDeleted(playerObj)){
ObjRender_SetPosition(playerObj,GetPlayerX,GetPlayerY,0);
yield;
}
}
task renderPlayer{
ObjPrim_SetTexture(playerObj, playerSprite);
Obj_SetRenderPriority(playerObj, 0.31); //This is your error
ObjSprite2D_SetSourceRect(playerObj, 0,0,32,32);
ObjSprite2D_SetDestCenter(playerObj);
}
task TExtends(){
let EXTENDS = [10000000, 30000000, 80000000];
let extend_count = 0;
while(extend_count < length(EXTENDS)){
if(GetScore() >= EXTENDS[extend_count]){
SetPlayerLife(GetPlayerLife() + 1);
extend_count++;
}
yield;
}
}
alternative(GetEventType())
case(EV_GET_ITEM){
if(GetEventArgument(0) == ITEM_1UP){
SetPlayerLife(GetPlayerLife() + 1);
}
}
Well, this is depressing. My player script isn't even being recognized. It is in the player directory.Not sure which version of ph3 you're running, but try #TouhouDanmakufu[Player] instead of the Japanese expression.
Code:
http://pastebin.com/9NkXFmFG
http://pastebin.com/TEbv6dCg
That's what I had originally, and then I changed it to see if this would work. Perhaps I mis-typed it originally? I'll try again...You need to completely close and restart Danmakufu in order to reload the script. Changing it on the fly won't make it appear.
You need to completely close and restart Danmakufu in order to reload the script. Changing it on the fly won't make it appear.
Not sure which version of ph3 you're running, but try #TouhouDanmakufu[Player] instead of the Japanese expression.
Edit: Ok this seems to be a similar case of file encoding which Fluffy had pointed out here (https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1240324.html#msg1240324) :). If you use #東方弾幕風[Player] you need proper UTF-8 encoding for your player script to make it show up. Otherwise use the regular English expression.
task Tran{
let target = GetTransitionRenderTargetName();
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj, target);
Obj_SetRenderPriority(obj, 0.1);
ObjSprite2D_SetSourceRect(obj, 0, 0, 640, 480);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetPosition(obj, 320, 240, 0);
while(true){
ObjSprite2D_SetSourceRect(obj, 0, 0, 640, 480);
yield;
}
}
task testRender {
wait(60);
let tex = GetTransitionRenderTargetName;
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj,tex);
ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
ObjRender_SetAlpha(obj,255);
Obj_SetRenderPriorityI(obj,80);
ObjRender_SetScaleXYZ(obj,1,1,0);
ObjSprite2D_SetSourceRect(obj,0,0,256,256);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetPosition(obj,200,100,0);
}
let tex = GetTransitionRenderTargetName;
RenderToTextureA1(tex, 0, 100, true);
PauseStageScene(true);
// Summon your pause script.
Thanks for the help, the problem has been fixed. Andddd I have another question : how can I create bullets that do not destroy when they leave the frame / gamefield?
Thanks for the help, the problem has been fixed. Andddd I have another question : how can I create bullets that do not destroy when they leave the frame / gamefield?You can also determine at which distance from each side outside of the stage frame the bullets should be deleted:
SetShotAutoDeleteClip( distance from the left side, top side, right side, bottom side);
Maybe it will be a stupid question, but?I think you're going to have to be more specific. What aspects of Ph3's drawing do you think are inadequate? If it's the resolution, than that can be changed from the default 640x480 to most any resolutions that you may desire, which should improve graphical fidelity by a lot. The only caveat is that you'd need textures (particularly bullet graphics and sprites) that can work with that resolution.
Is there really no way to improve ph3 graphics drawing?
It's really annoying, it kills graphic quality too much.
Maybe it will be a stupid question, but?
Is there really no way to improve ph3 graphics drawing?
It's really annoying, it kills graphic quality too much.
Alrighty, so out of personal interest I coded this up. Writing code for generic gradius options was pretty easy; setting it up like MoF where focus movement locks the options was much more difficult and I had to rework the approach a few times.
https://gist.github.com/drakeirving/1ef0f9a315468dc864a678caf550116b
As always, I aimed to make this as generic as possible. The number of options is arbitrary, and with the non-player version you can attach options to any Move object (e.g. a bullet).
You could very easily modify the for-player version to fire bullets and work properly when the player dies, which I didn't bother with.
My Stage script starts to lag gradually about a minute after initiating the plural script. After 2 minutes, there's already only about 15FPS.Doesn't needs to be undeleted objects. Could be something that spawns endless number of threads being started doing things endlessly. Btw, missing yields cannot cause lag (directly). A missing yield in a loop would insta-freeze your game. A missing yield in a regular task with no loop would instant finish the the task and then become 'dead'.
I checked and debugged my script many times, I came to realize it's definitely not an undeleted object, or a missing "yield;", and I still don't know what it is.
Is there a reason as to why my script might lag so much?
I came to realize it's definitely not an undeleted object, or a missing "yield;", and I still don't know what it is.
task foo( let bar )
{
// ex1:
loop
{
...
// no break
}
// ex2:
let baz = true;
while( baz )
{
...
// baz not accessed, no break
}
}
So, by good ol' trial and error, I managed to find the problem.You'll need more trial and error. The fun just started.
It's the system file. :o
I still can't find the issue with it. I'm 100% sure there are no problems with the pause and replay scripts, because when I excluded them from the system file, the lag still persisted.
I've been looking at it for hours now, and I'm still struggling. (I swear if it's going to be something glaringly obvious--)
Here's my system script. (http://pastebin.com/gFubChRf)
Well, it is as I suspected. There is a reason why I told you to observe your Log Window. It is your best friend with detecting lag and such. Always use it when debugging/testing these things. If you haven't activated your log window. Shame on you! :flamingv:
No idea what you're trying to achieve here.
To be honest, neither do I.Ooh, now I remember. Yea the little bars under the lifebar, counting the number of spell cards.
I should have put "ObjPrim_Create(OBJ_SPRITE_2D);" at the start of the task, not in the RenderLife function. (By the way, it's supposed to be a lifebar container thingy.)
So, I really didn't want to clog up this thread with myself again, but...
WHAT THE ACTUAL HELL IS WRONG WITH THIS SCRIPT. (http://pastebin.com/FZZrfj7A) (<- link) It seems to be stable, yet Danmakufu keeps yelling at me!
Check for missing semicolons, }, and ) in all of your #include files.
The script worked perfectly before I added the two tasks I talked about in my post, so I don't think there's a problem with my #include files.
You have : instead of ; in various places in your script.
I just added functionality to sublime-danmakufu (https://www.shrinemaiden.org/forum/index.php/topic,16965.0.html) to highlight colons as invalid characters for this reason (whether you're using it or not). They really don't have any meaning in the language, so hey whatever.
Hopefully someone makes a version for NP++ (though it could be much harder).I actually have such a version. I cannot remember where I found it, but I'm pretty sure it was not from here. It's semi outdated but adequate for me. I could try to get it up to date and send it to you if you haven't become too attached to Sublime already.
I actually have such a version. I cannot remember where I found it, but I'm pretty sure it was not from here. It's semi outdated but adequate for me. I could try to get it up to date and send it to you if you haven't become too attached to Sublime already.
No need to, actually found one on these forums. (https://www.shrinemaiden.org/forum/index.php?topic=18133.0)The last update Danmakufu Ph3 received was in January 2015, two months before that post was made. So assuming the person who made it was thorough, it should be complete and up to date. Might have to try that one myself.
It's for ph3, and it also supports the Bespin theme, which is nice. Not quite sure if it's up to date or not.
I need help figuring out how to implement this gameplay feature in my danmakufu project.
Basically what I want is a character that only gets shot down only if 2 or more bullets are touching the players hitbox.
At first I thought making this work would be easy. My initial idea was to have the hitbox disabled unless a bullet was touching a phantom hitbox, but I realized that the bullet that activated the phantom hitbox would immediately trigger the real one unless I could identify the exact bullet touching the phantom hitbox and making sure it wouldn't trigger a death.
Does anyone have an idea if making a hitbox that can ignore a particular object ID can be done?
task tHitBox
{
loop{
while (length(GetShotIdInCircleA1(GetPlayerX,GetPlayerY,8))>1){
ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 100, 20);
yield;
}//while
ObjPlayer_ClearIntersection(objPlayer);
yield;
}//loop
}
How do I make star shaped danmaku (like Sanae)?
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["EX Rumia Plural Script"]
#Text["EX Rumia Spell Cards"]
#Image[".\img\ExRumia(?????u?~?b?h?i?C?g?????@???G?v).png"]
#Background["script/default_system/Default_Background_IceMountain.txt"]
@Initialize
{
TPlural();
}
@MainLoop
{
yield;
}
@Finalize
{
}
task TPlural
{
let dir = GetCurrentScriptDirectory();
//Creates the boss scene
let obj = ObjEnemyBossScene_Create();
ObjEnemyBossScene_Add(obj, 0, dir ~ "boss1attack1.txt");
ObjEnemyBossScene_Add(obj, 0, dir ~ "boss1attack2hard.txt");
ObjEnemyBossScene_LoadInThread(obj);
ObjEnemyBossScene_Regist(obj);
//Stands by until the boss scene is finished
while(!Obj_IsDeleted(obj))
{
yield;
}
//The end of the script
CloseScript(GetOwnScriptID());
}
I'm having a problem.
I'm trying to make a plural stage, but now it's crashing Danmakufu whenever I run it.
The nonspells are boss1attack1 and boss1attack2hard. Why isn't it going to load?
let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
ObjPrim_SetPrimitiveType(obj,PRIMITIVE_TRIANGLESTRIP);
ObjPrim_SetTexture(obj,GetCurrentScriptDirectory ~ "MG1.png");
Obj_SetRenderPriority(obj, 0.69);
ObjPrim_SetVertexCount(obj,64);
ascent(a in 0..64){
ObjSpriteList2D_AddVertex(obj);
ObjSprite2D_SetSourceRect(obj, 1024/64*(a), 0, 1024/64*(a+1), 64);
ObjSprite2D_SetDestCenter(obj);
ObjPrim_SetVertexPosition(obj,a,bossX+64*cos(a*360/64),bossY+64*sin(a*360/64),0);
}
ObjSpriteList2D_CloseVertex(obj);
ObjRender_SetBlendType(obj,BLEND_ADD_RGB);
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["EX Rumia Plural Script"]
#Text["EX Rumia Spell Cards"]
#Image[".\stage/derp.png"]
#Background["script/default_system/Default_Background_IceMountain.txt"]
@Initialize
{
TPlural();
}
@MainLoop
{
yield;
}
@Finalize
{
}
task TPlural
{
let dir = GetCurrentScriptDirectory();
//Creates the boss scene
let obj = ObjEnemyBossScene_Create();
ObjEnemyBossScene_Add(obj, 0, dir ~ "boss1attack1.txt");
ObjEnemyBossScene_Add(obj, 0, dir ~ "boss1attack2hard.txt");
ObjEnemyBossScene_LoadInThread(obj);
ObjEnemyBossScene_Regist(obj);
//Stands by until the boss scene is finished
while(!Obj_IsDeleted(obj))
{
yield;
}
//The end of the script
CloseScript(GetOwnScriptID());
}
#Image[".stage/derp.png"]
#Background["script/default_system/Default_Background_IceMountain.txt"]
Use a forward slash instead of a backslash.
Code: [Select]#Image[".stage/derp.png"]
#Background["script/default_system/Default_Background_IceMountain.txt"]
Delete that code. Maybe that's the problem.
Hi!
Is there a way to manually open the pause script? Like a function when it called it open the pause menu without pressing any pause key?
I want to create a pseudo-continue system that occur before the actual danmakufu gameover by oppening a pause script but I don't know how to freeze the game during the pause menu and unfreeze it when the player leave the menu.
I can't delete the code. I managed to cobble together a working #SetScriptPath and it worked but the boss didn't spawn. What do?
Hi!There is probably an acceptable way to accomplish what you're thinking of, so maybe you should describe it in more detail rather than asking for a particular kind of solution.
Is there a way to manually open the pause script? Like a function when it called it open the pause menu without pressing any pause key?
I want to create a pseudo-continue system that occur before the actual danmakufu gameover by oppening a pause script but I don't know how to freeze the game during the pause menu and unfreeze it when the player leave the menu.
Well. I just want to create a continue system without using the package script. So I thought to use a simple Pause menu with options like in a Game Over menu (but I still keep a true pause menu beside). And I want to call this menu when it remain one life (with this, I avoid the true danmakufu end menu).
But I have no idea how I can do this.
(I hope it's almost clear :ohdear:)
edit: I think I actually found a way to do that by using a common data in my main script and opening pause script in package script with this. But I don't know if it's possible to do without a package script...
Well. I just want to create a continue system without using the package script. So I thought to use a simple Pause menu with options like in a Game Over menu (but I still keep a true pause menu beside). And I want to call this menu when it remain one life (with this, I avoid the true danmakufu end menu).I have made this precise system you're looking for in my game, Ephemeral Unnatural Balance. You are correct in your thought process, however the only way to induce the game to pause outside of pressing the Pause key is to use this function: PauseStageScene
But I have no idea how I can do this.
(I hope it's almost clear :ohdear:)
edit: I think I actually found a way to do that by using a common data in my main script and opening pause script in package script with this. But I don't know if it's possible to do without a package script...
This is just impossible...
There's at least one error in this that is causing Danmakufu to crash, and I cannot find it. I need it to be fixed so I can have the workings of a finished game.
Can someone tell me why the ExRumia demo script works with a plural, but not this?
Try placing a few yields at the very start of the task. This seems to be a prevalent problem with Danmakufu.Wat. I've never had this sort of problem, and it makes no sense to arbitrarily yield tasks for a frame. This was a problem in 0.12 if you wanted to start a task that tried to render image resources before @Initialize was finished (or something along those lines, it's been a while), but ph3 doesn't have this issue.
let obj = ObjEnemyBossScene_Create();
out of any task or @ instead of in the TPlural. If you put it in TPlural, obj will exist only in this task and not in the entire script.Nefer> TryIt shouldn't matter, since the Scene object isn't referenced outside the task. Having it be undefined outside the task and trying to reference it would throw an error instead of crashing anyways.Code: [Select]let obj = ObjEnemyBossScene_Create();
out of any task or @ instead of in the TPlural. If you put it in TPlural, obj will exist only in this task and not in the entire script.
I'm not sure ti was the problem but It's a bit wreid for me.
let path2 = current~ "cdbg06a.png";
let bg2 = ObjPrim_Create(OBJ_PRIMITIVE_2D);
ObjPrim_SetPrimitiveType(bg2,PRIMITIVE_TRIANGLEFAN);
ObjRender_SetBlendType(bg2, BLEND_SUBTRACT);
Obj_SetRenderPriority(bg2, 0.21);
ObjPrim_SetTexture(bg2, path2);
ObjSprite2D_SetDestRect(bg2,-0, 0, GetX, GetY);
let t = 0;
let ti = 10;
let alpha = 0;
loop{
determine;
if(isSpell){alpha=1;}
else{alpha=0;}
let px = GetCenterX;
let py = GetCenterY-150;
let vc = 62;
ObjSprite2D_SetDestCenter(bg2);
ObjPrim_SetVertexCount(bg2,vc);
ObjPrim_SetVertexPosition(bg2,0,px,py,1);
ObjPrim_SetVertexUVT(bg2,0,512*(t/300),1048);
ascent(i in 0..vc){
ObjPrim_SetVertexPosition(bg2,i+1,px+ti*cos((360/(vc-3))*i-90),py+ti*sin((360/(vc-3))*i-90),1);
ObjPrim_SetVertexAlpha(bg2,i,alpha*200);
}
ascent(i in 0..vc){
ObjPrim_SetVertexUVT(bg2,i+1,0,(512/vc*5)*i);
}
ObjPrim_SetVertexPosition(bg2,vc-1,px+ti*cos(0-90),py+ti*sin(0-90),1);
ObjPrim_SetVertexUVT(bg2,vc-1,0,512);
ObjPrim_SetVertexAlpha(bg2,vc-1,alpha*200);
t++;
ti+=1;
yield;
}
Hi! It's not an actual question about danmakufu but more a question about organisation and project making. I ask this espacially to people who make actual full games.
How do you organize your work? What do you make first? Danmaku or all the menus and system? And about all graphics and sounds? And about scenario?
I start new full game project but I don't really know (or I actually know but I want others advinces and experiences) how to plan my task and I know how it's really hard to stay in the right way.
task DeleteShotToItem(x,y,radius,type,deltype) { //Deletes bullets and leaves a bullet break image
let iArray = GetShotIdInCircleA2(x,y,radius,TARGET_ENEMY);
ascent(i in 0..length(iArray)) {
let col = ObjShot_GetImageID(iArray[i]);
let color = GetShotDataInfoA1(col,TARGET_ENEMY,INFO_DELAY_COLOR); //Line where the error occurs
DelEffect(GetX(iArray[i]),GetY(iArray[i]),type,[color[0],color[1],color[2]]);
DeleteShotInCircle(TYPE_ALL,deltype,GetX(iArray[i]),GetY(iArray[i]),2);
}
task DelEffect(x,y,typ,Col) { //Bullet break image task
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
let path = GetCurrentScriptDirectory~"./img/Effect/BulletBreak.png";
Obj_SetRenderPriorityI(obj,35);
ObjPrim_SetTexture(obj,path);
ObjRender_SetPosition(obj,x,y,0);
ObjSprite2D_SetSourceRect(obj,0,0,32,32);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetColor(obj,Col[0],Col[1],Col[2]);
ObjRender_SetAlpha(obj,200);
ObjRender_SetScaleXYZ(obj,0.5,0.5,0);
ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
ascent(i in 0..8) {
ObjSprite2D_SetSourceRect(obj,32*(i-1),0,32*i,32);
wait(5);
}
Obj_Delete(obj);
}
}
I *highly* recommend having one folder specifically for images that will hold EVERY image asset you use in your game. This way it's very easy to archive later on, and you always know where things are.Do you mean a separated file where you put every images used in any way in the project with .psd and all other layered stuff or an actual file of the game with all the images in?
Thanks Sparen.
Just about this:Do you mean a separated file where you put every images used in any way in the project with .psd and all other layered stuff or an actual file of the game with all the images in?
So, now I need to found someone to make me cool musics before I can start stage and bosses making :(
If someone else have advices about full game making, don't hesitate ^^. I have almost my way to do but other point of view are always a good thing ;).
I *highly* recommend having one folder specifically for images that will hold EVERY image asset you use in your game. This way it's very easy to archive later on, and you always know where things are.You mean "have every images used in the game in one unique picture folder in the game file" right? And not "keep every .psd and other in one unique folder out of the game folder".
That's exactly what I'm doing. Actually my ask is:
By this: You mean "have every images used in the game in one unique picture folder in the game file" right? And not "keep every .psd and other in one unique folder out of the game folder".
I'm not sure if it's clear or not :(
task TBossTimer
{
let objNum = ObjText_Create;
let objScene;
loop{
objScene = GetEnemyBossSceneObjectID();
while(objScene != ID_INVALID){
RenderTimer;
}
yield;
}
function RenderTimer{
while(objScene == ID_INVALID){yield;}
let timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);
ObjText_SetFontSize(objNum, 24);
ObjText_SetText(objNum, rtos("00", timer));
ObjText_SetFontType(objNum, "Russell Square Regular");
ObjText_SetFontBold(objNum, true);
ObjText_SetFontColorTop(objNum, 255, 255, 255);
ObjText_SetFontColorBottom(objNum, 255, 255, 255);
ObjText_SetFontBorderType(objNum, BORDER_FULL);
ObjText_SetFontBorderColor(objNum, 0, 0, 0);
ObjText_SetFontBorderWidth(objNum, 2);
Obj_SetRenderPriority(objNum, 0.5);
ObjRender_SetX(objNum, 395);
ObjRender_SetY(objNum, 2);
while(true){
timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);
timer = min(timer, 999);
ObjText_SetText(objNum, rtos("00", timer));
yield;
}
}
}
My timer works only during the midboss; It just stays at zero during the boss battle. Any reasons why? It works well when I use the default timer. (You might see some random useless garbage thrown in to the code, but that's just because I've been going crazy to fix it for like 3 days.)The issue might be because the timer doesn't delete after a single script is closed. Here's the code with not that issue when playing it in single scripts, i might test it with plurals later but i got to go right now :
task TBossTimer
{
let objNum = ObjText_Create;
let objScene;
loop{
objScene = GetEnemyBossSceneObjectID();
if(objScene != ID_INVALID){
RenderTimer;
}
yield;
}
function RenderTimer{
let timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);
ObjText_SetFontSize(objNum, 24);
ObjText_SetText(objNum, rtos("00", min(timer,999)));
ObjText_SetFontBold(objNum, true);
ObjText_SetFontColorTop(objNum, 255, 255, 255);
ObjText_SetFontColorBottom(objNum, 255, 255, 255);
ObjText_SetFontBorderType(objNum, BORDER_FULL);
ObjText_SetFontBorderColor(objNum, 0, 0, 0);
ObjText_SetFontBorderWidth(objNum, 2);
Obj_SetRenderPriority(objNum, 0.5);
ObjText_SetFontType(objNum, "Russell Square Regular");
ObjRender_SetX(objNum, 395);
ObjRender_SetY(objNum, 2);
loop(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER)*60) {
timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);
ObjText_SetText(objNum, rtos("00", min(timer,999)));
yield;
}
Obj_Delete(objNum);
}
}
//----------------------------------------------------
//BOSS TIMER
//----------------------------------------------------
task TBossTimer {
let timer = -1;
let time01_path = GetCurrentScriptDirectory() ~ "se/se_timeout.wav";
let time02_path = GetCurrentScriptDirectory() ~ "se/se_timeout2.wav";
let timer_end = false;
let f = 0;
let count = 5;
let num_id = [ObjText_Create,ObjText_Create,ObjText_Create,ObjText_Create,ObjText_Create,ObjText_Create];
let sep = "";
let sep_space = 6;
let size_min = -6;
let pulse = 0;
let r = 0;
let listNum = DigitToArray(timer, 5);
let objScene = ID_INVALID;
let taskOn = true;
ascent(iObj in 0 .. 5) {
if((4-iObj) == 2) {
sep_space = 0;
size_min = 0;
}
if((4-iObj) == 3) {
sep_space = 0;
}
let num = listNum[4-iObj];
Text(num_id[4-iObj], "",196-iObj*12+sep_space, 14-0.75*size_min, 18+size_min, 255, 255-r, 255-r, 255, 255-r, 255-r, 8+r, 8, 8, 0.70);
}
while(taskOn == true) {
objScene = GetEnemyBossSceneObjectID();
if(objScene == ID_INVALID) {
ascent(iObj in 0 .. 5) {
let num = listNum[4-iObj];
if((4-iObj) == 3) {
if((iObj) < count) {
sep = ",";
} else if((iObj) == count) {
sep = " ";
}
} else {
sep = "";
}
ObjText_SetText(num_id[4-iObj], "");
}
} else if(objScene != ID_INVALID) {
if(timer == -1) {timer = 100*ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);}
if(timer < 100*ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER)) {timer = 100*ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);}
f += 1/0.6;
timer -= 1/0.6;
if(timer < 0) {timer = 0;}
if(timer > 1000) {r = 0;}
if(timer <= 1000) {r = 80;}
if(timer <= 500) {r = 120;}
if(timer <= 1000 && timer > 997) {
SE(time01_path);
timer_end = false;
}
if(timer <= 900 && timer > 897) {SE(time01_path);}
if(timer <= 800 && timer > 797) {SE(time01_path);}
if(timer <= 700 && timer > 697) {SE(time01_path);}
if(timer <= 600 && timer > 597) {SE(time01_path);}
if(timer <= 500 && timer > 495) {SE(time02_path);}
if(timer <= 400 && timer > 395) {SE(time02_path);}
if(timer <= 300 && timer > 295) {SE(time02_path);}
if(timer <= 200 && timer > 195) {SE(time02_path);}
if(timer <= 100 && timer > 95) {SE(time02_path);}
if(timer <= 0 && timer_end == false) {
SE(time02_path);
timer_end = true;
}
count = truncate(log10(1+timer));
if(count < 3) {count = 3;}
let listNum = DigitToArray(timer, 5);
ascent(iObj in 0 .. 5) {
let num = listNum[4-iObj];
if((4-iObj) == 3) {
if((iObj) < count) {
sep = ",";
} else if((iObj) == count) {
sep = " ";
}
} else {
sep = "";
}
if((iObj) > count) {
ObjText_SetText(num_id[4-iObj], "");
} else {
ObjText_SetText(num_id[4-iObj], sep ~IntToString(num));
}
ObjText_SetFontColorTop(num_id[4-iObj], 255, 255-r, 255-r);
ObjText_SetFontColorBottom(num_id[4-iObj], 255, 255-r, 255-r);
ObjText_SetFontBorderColor(num_id[4-iObj],8+r, 8, 8);
}
}
yield;
}
}
(don't mind about while(taskOn == true), I don't know loop{stuff} works when I wrote this).It doesn't work. All it changed is that it now deletes the whole timer after the boss appears. Also, I specifically said it worked well with the midboss, but stopped working during the boss, meaning I'm making a Stage script, not a Single or Plural script. It works perfectly in Single.
task BossTimer
{
let objScene;
loop{
objScene = GetEnemyBossSceneObjectID();
if(objScene != ID_INVALID){
RenderTimer;
}
yield;
}
function RenderTimer{
let objNum = ObjText_Create;
let timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);
ObjText_SetFontSize(objNum, 24);
ObjText_SetText(objNum, rtos("00", min(timer,999)));
ObjText_SetFontBold(objNum, true);
ObjText_SetFontColorTop(objNum, 255, 255, 255);
ObjText_SetFontColorBottom(objNum, 255, 255, 255);
ObjText_SetFontBorderType(objNum, BORDER_FULL);
ObjText_SetFontBorderColor(objNum, 0, 0, 0);
ObjText_SetFontBorderWidth(objNum, 2);
Obj_SetRenderPriority(objNum, 0.5);
ObjText_SetFontType(objNum, "Russell Square Regular");
ObjRender_SetX(objNum, 395);
ObjRender_SetY(objNum, 2);
while(GetEnemyBossSceneObjectID() != ID_INVALID) {
timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER);
ObjText_SetText(objNum, rtos("00", min(timer,999)));
yield;
}
Obj_Delete(objNum);
}
}
I have tested this in a stage setting and it indeed works. Hope my explanation make sense, I'll try to explain more if you're still unsure.Highly intelligent stuff.
Oh, I can see why it didn't work now. Thank you so much for helping me with the problem, your explanation was superb.Don't sweat it, it was actually a fun problem to debug. Until my debug functions needed debugging...
I seem to be remarkably good at making chains of accidental infinite loops :V
Don't sweat it, it was actually a fun problem to debug. Until my debug functions needed debugging...
Hi, I needed some help with my spell background.Hi, I had forgotten about this. I saw it and set it aside for later because I knew it'd be problematic and I didn't want to think about how to do it properly, and just never got back to it until recently.
I've been trying to replicate Junko's background but there are some (lots of) problems.
http://imgur.com/a/5JhDp (I don't know how to attach images...)
In the first picture there's a line where the bg originate out from, I want it to originate from a specific point, not from a line.
In the second picture, as the time passes on, the bg becomes stretched out and more uniformed, I don't want this to happen.
Hello guys, I'm new here and in Danmakufu 0.12m.There are at least a couple tutorials for animation in 0.12m like this one. (https://www.youtube.com/watch?v=JUj6xG79-TY) It's old, but so is 0.12m (I really recommend you learn ph3 instead).
can someone help me anim this sprite for danmakufu 0.12m?
https://www.mediafire.com/?5pdgyuentafdm4v <--- Flandre Scarlet sprite..
please guys help me! T_T
I've been searching the wiki and the official documentation, and I've been wondering, how does danmakufu handle dictionaries / associative arrays (if at all)?
You can use common data instead, or you can implement hashtables yourself.Common data seems to be a rough fit for what I'm looking to do, thanks
You can very much use the exact same functionality as CommonData without messing around with global scope clutter by using Obj_SetValue and GetValue. It's probably a sort of hashing implementation under the hood anyways; the main barrier is that they need an object to be attached to and there isn't any kind of truly generic object. You can effectively work around this by just using an Enemy object and never registering it.This seems to be a much better fit, can't believe I missed this, thanks.
How do I take the texture of the stage BEFORE it finishes (I?m talking about packages), so I wouldn?t have a black background?
http://pastebin.com/BaAFBkfw
function ObjSpriteList2D_SetAlpha(obj, a){
ascent(v in 0..ObjPrim_GetVertexCount(obj)){
ObjPrim_SetVertexAlpha(obj, v, a);
}
}
task Bullet(x, y, v, angle,delaie) {
let papillon=ObjShot_Create(OBJ_SHOT);
ObjShot_Regist(papillon);
ObjMove_SetX(papillon, x);
ObjMove_SetY(papillon, y);
ObjMove_SetAngle(papillon, angle);
ObjMove_SetSpeed(papillon, v);
ObjShot_SetGraphic(papillon, 107);
ObjShot_SetDelay(papillon, delaie);
ObjShot_SetSpellResist(papillon, true);
ObjShot_SetAutoDelete(papillon,false);
change(papillon);
}
task change(papillon){
while(ObjEnemy_GetInfo(objEnemy, INFO_LIFE)>=500){
yield;
}
ObjMove_SetSpeed(papillon, -3 );
}
ObjMove_SetSpeed(papillon, 3);
ObjMove_SetAngle(papillon, ObjMove_GetAngle(papillon) + 180);
task Bullet(x, y, v, angle,delaie) {
let papillon=CreateShotA1(x,y,v,angle,107,delaie);
ObjShot_SetSpellResist(papillon, true);
ObjShot_SetAutoDelete(papillon,false);
change(papillon);
}
task change(papillon){
while(ObjEnemy_GetInfo(objEnemy, INFO_LIFE)>=500){
yield;
}
ObjMove_SetSpeed(papillon, 3);
ObjMove_SetAngle(papillon, ObjMove_GetAngle(papillon) + 180);
}
What do you have in your @MainLoop?
You forgot to yield in your @MainLoop.
Wait ... really !?
Now it works !
I've never included any "yield" in my mainloop scripts. I'm going to correct that.
Thanks you very much !
I've never included any "yield" in my mainloop scripts. I'm going to correct that.That is because as soon as you're using tasking and threading, you always need to. In your script, you're using a combination of mainloop and tasking, so you need to yield your mainloop.
To explain more precisely:
At #161 you're invoking a while loop which is a way of tasking/threading. That section will never get a chance to run. The MainLoop is the first thread being launched when your script loads. Yielding MainLoop allows the engine check for any other tasks/threads to run/execute.
task TEnd at #130 is not a thread as it contains no loop. It is more like a method with a plain if-statement. And that method is called within the MainLoop, so it will execute.
task change(papilion) is called from Bullet in #153 and Bullet is again called from the MainLoop. The bullet will appear fine. Each bullet will also successfully call its change(papilion) task, but none of these will ever run/execute because the MainLoop doesn't allow it.
Hello!
I wasn't sure if this merited a new thread or not, so I apologize if I've put this in the wrong place... what are some good example scripts a beginner can look at to see certain patterns and techniques in action? I'm particularly interested in seeing spell cards or full bosses with cut-ins and text because I haven't really seen how to do those (I've checked a few tutorials and it's slowly coming together for me, but I'm still really weak on scripting). Thanks!
let idScript = LoadScript (pathToScript);
SetScriptArgument(idScript, 2, var);
StartScript(idScript,var);
// But since StartScript has only 1 argument, I've also tried
let idScript = LoadScript (pathToScript);
SetScriptArgument(idScript, 2, var);
StartScript(2);
Hello everyone !The way that SetScriptArgument works is:
I would like to use the function : "SetScriptArgument" in order to transfer some variables from a script to another, but due to my bad english, I have a lot of troubles for understanding how it works.
I've loaded my script, used setScriptArgument and then startScript like the wiki says :Code: [Select]let idScript = LoadScript (pathToScript);
SetScriptArgument(idScript, 2, var);
StartScript(idScript,var);
// But since StartScript has only 1 argument, I've also tried
let idScript = LoadScript (pathToScript);
SetScriptArgument(idScript, 2, var);
StartScript(2);
But nothing work, I tried other combinations and I've looked up for more explanations about this function but I didn't found anything else than danmakufu wiki.
If someone can explain me how this function works, I would be grateful.
Edit : I mean, this argument is a bgm, otherwise, I would have used commondata
Thanks in advance !
//First script
let idScript = LoadScript (pathToScript);
SetScriptArgument(idScript, 2, var);
StartScript(idScript);
//Second script (the one you just started)
let newvar = GetScriptArgument(2);
//Then you can just use it as normal
PlayBGM(newvar);
As you can see, the new script is passed the variable which you can access using GetScriptArgument.The way that SetScriptArgument works is:
-You give the script the value using SetScriptArgument
-You start the script as normal
-You then retrieve the variable in the started script
That is:Code: [Select]//First script
As you can see, the new script is passed the variable which you can access using GetScriptArgument.
let idScript = LoadScript (pathToScript);
SetScriptArgument(idScript, 2, var);
StartScript(idScript);
//Second script (the one you just started)
let newvar = GetScriptArgument(2);
//Then you can just use it as normal
PlayBGM(newvar);
Hope this helps
^^^^
...
...
@Initialize{
objBoss = ObjEnemy_Create(OBJ_ENEMY_BOSS);
ObjEnemy_Regist(objBoss);
ObjEnemyBossScene_StartSpell(objScene);
ObjPrim_SetTexture(objBoss, imgExRumia);
ObjSprite2D_SetSourceRect(objBoss, 64, 1, 127, 64);
ObjSprite2D_SetDestCenter(objBoss);
ObjMove_SetDestAtSpeed(objBoss, 82, 100, 100);
//Instead of starting your MainTask in @MainLoop, you should start it in @Initialize and make MainTask loop
MainTask;
}
@MainLoop{
bossX = ObjMove_GetX(objBoss);
bossY = ObjMove_GetY(objBoss);
yield;
} <--- Insert here
task MainTask{
//Rather than looping in fireA, you shoudl loop here and have MainTask call fireA each time
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){ <---Move from "fireA"
let wait = 120; //What is this for? For now, let's make it loop "wait" amount of frames with the next line:
loop(wait){yield;} //One of the greatest bits of code you'll use in Danmakufu. Remember it
fireA;
}
task fireA{
let angleT = 0;
loop(30){
CreateShotA1(bossX + 90*cos(angleT), bossY + 90*sin(angleT), 2, angleT, 1, 0);
angleT += 360/30;
}
}
} <---Insert here
...
...
// Plain loop which runs as long as the script is active. Delay is 1 frame at the end of the loop.
loop {
CreateShotA1(....);
yield;
}
// Plain loop which runs 10 times. Delay is 1 frame at the end of the loop.
loop(10) {
CreateShotA1(....);
yield;
}
// A while loop which will execute as long as the bossObj is NOT deleted (alive). Delay is 1 frame at the end of the loop.
while(!Obj_IsDeleted(bossObj)) {
CreateShotA1(....);
yield;
}
// A while loop which will execute as long as 'counter' is smaller than 10. Each loop, 'counter' is increased by 1. Delay is 1 frame at the end of the loop.
let counter = 0;
while(counter < 10) {
CreateShotA1(....);
counter++;
yield;
}
Hello again!
How can I make sure all my fonts are installed correctly at the start of my script?
let fontstoload = ["path1", "path2", "etc"];
let checkloadedfont = true;
ascent(nF in 0..length(fontstoload)) {
if(! InstallFont(fontstoload[nF])) {
checkloadedfont = false;
// do other things here as well, for example, giving a visual notification that a particular font failed.
}
}
task MagicPoints(x,y){
// Randomly chooses one of the four sprites form the sprite sheet.
let ex = rand2(128,128+32);
let ey = rand2(0,32);
let path = GetCurrentScriptDirectory() ~ "img/sprite/items.png";
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj, path);
ObjMove_SetPosition(obj,x,y); // Doesn't work
Obj_SetRenderPriority(obj, 100);
ObjSprite2D_SetSourceRect(obj, ex, ey, ex+32, ey+32);
ObjSprite2D_SetDestRect(obj, ObjMove_GetX(obj), ObjMove_GetY(obj), ObjMove_GetX(obj)+32, ObjMove_GetY(obj)+32);
ObjMove_SetSpeed(obj,2); // Doesn't work
ObjMove_SetAngle(obj,90); // Doesn't work
loop{
// When the player gets close to the item it's deleted and the item count is updated.
if(ObjecttoPlayer(obj) <= 4){
//PlaySound(shot1);
Scores += 1;
Obj_Delete(obj);
}
yield;
}
}
I'm trying to make my own point item from scratch, I can draw the sprite, but I can't get the object to move at all or set it's position.Code: [Select]
I'm having this issue where my laptop can't read(?) player scripts that I download. Not sure if this is for any custom player script or just certain ones, since the default Rumia player script works just fine. These player scripts work on my desktop however, and both have their system locale set to Japanese. They simply don't show up on the list of player scripts when I open up the Danmakufu program, and when I use the DnhViewer, I can't interact with anything and I'm forced to close it and move my custom player scripts elsewhere and stick with the Rumia script when I work on my laptop. My Danmakufu folder is kept on a flashdrive so it's gotta be the computer's fault. I haven't made my own player script yet, as I'm just playing around with the engine, getting a feel for it, so I'm temporarily using this Mountain of Faith Reimu script someone made ( http://www.bulletforge.org/u/frenticpony/p/player-re-creation-project-mof-reimu ).
I haven't tried using AppLocale, just changed the system locale, but I don't see how that'd make a difference since I do the same on my desktop. Both are Windows 7.
UPDATE: Maybe related to the files in the player script folder? Found out that an .ogg file in my own script folder was causing DNHViewer to freeze up just like with the player scripts. Still can't quite narrow it down myself. I tried removing the sound library and SE folder for the Reimu script and that didn't work, so I dunno.
task OscReverse(obj){
wait(80);
ObjMove_SetSpeed(obj, -2);
}
task OscillateA{
while(ObjEnemy_GetInfo(objBoss,INFO_LIFE) > 0){
let angleT = GetAngleToPlayer(objBoss);
loop(13){
ascent(i in 0..3){
let obj = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 1.5 - i/6, angleT, DS_BUTTERFLY_RED + i, 5);
OscReverse(obj)
}
angleT += 360/13;
yield;
}
wait(120);
}
}
task LifeItem(x,y){
let obj = CreateItemU1(1,x,y,0);
while(!Obj_IsDeleted(obj)){yield;}
PlaySE(shot1);
LifeFragment += 3;
}
GetPlayerLife and ObjMove_GetX are both standard functions, so I don't understand why having them called in menu script is causing problems.I think it's because these functions are not defined in the Package Script. Pause Menu is called in the Package and depend of it. Even if a Stage Script is runnig.
360 - angle + 2 * surface
where angle is the angle of the object and surface is the angle of surface.angle + 90
where 90 is the angle from the object to the center of the circle.
newangle = 360 - ObjMove_GetAngle(obj) + 2 * (atan2(ObjMove_GetY - CircleCenterY, ObjMove_GetX - CicleCenterX) + 90);
I think the angle of the surface is the same as the angle between the point were the object colide with the circle and the center of this circle. Right?So I made a player script using Helepolis's tutorial, but it always has the same crash report even if I do it word for word.Prim as in "Primitive"
The report reads as follows:
ObjPrism_Create is not defined.
I'm working on a custom pause menu, but there are two things I can't get working.
- Including a file of standard tasks and functions, I get an error saying ObjMove_GetX is not defined in the file I'm trying to have included.
- Trying to get the player's current life, I get GetPlayerLife is not defined.
GetPlayerLife and ObjMove_GetX are both standard functions, so I don't understand why having them called in menu script is causing problems.
Also I've got a simple item that can execute some commands when you collect it, but since it only checks if the item is deleted the same event will happen if it falls off-screen. How can I check if the item has been collected by the player?Code: [Select]task LifeItem(x,y){
let obj = CreateItemU1(1,x,y,0);
while(!Obj_IsDeleted(obj)){yield;}
PlaySE(shot1);
LifeFragment += 3;
}
So I made a player script using Helepolis's tutorial, but it always has the same crash report even if I do it word for word.
The report reads as follows:
ObjPrism_Create is not defined.
(ObjPrism_Createは未定義の識別子です)
G:/th_dnh_ph3/script/player/marisa/playermarisa.txt
playermarisa.txt line(行)=11
↓
let playerObj = ObjPrism_Create縺ッ譛ェ螳夂セゥ縺ョ隴伜挨蟄舌〒縺・;
let hitboxObj = ObjPrism_Create縺ッ譛ェ螳夂セゥ縺ョ隴伜挨蟄舌〒縺・;
let count = -1;
let isFocus = false;
// Shot Sheet
let shotMarisa = CSD ~ "playershot.txt";
// Texture Sheet
~~~
I don't understand why it won't work.
task LostWaves{
let angleT = rand(0, 360);
let objcount = 18;
loop{
loop(5){
let obj = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2, angleT, 45, 5);
angleT += 360/5;
wait(0.001);
}
angleT += sin(objcount) * 8;
if(objcount > 36){
objcount = 18;
angleT += cos(objcount) * 8;
}else{
objcount++;
}
yield;
}
}
angleT += sin(objcount) * 8;
if(objcount > 36){ // Note here
objcount = 18;
angleT += sin(objcount) * 8;
}else{
objcount++;
}
task LostWaves{
let angleT = rand(0, 360);
let objcount = 40;
//let oscount = 0;
loop{
loop(5){
let obj = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2, angleT, 45, 5);
angleT += 360/5;
wait(0.001);
}
//angleT += sin(objcount) * 8; //BOWAP- Sine makes the oscillation, * 6 ensures there are gaps.
if(objcount >= 240){
angleT -= sin(objcount) * 8;
objcount -= 3;
}else if(objcount <= 60){
angleT -= sin(objcount) * 8;
objcount += 3;
}else{
angleT -= sin(objcount) * 8;
objcount += 3;
}
yield;
}
}
task LostWaves{
let angleT = rand(0, 360);
let objcount = 40; // objcount is initialized here
//let oscount = 0;
loop{
loop(5){
let obj = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2, angleT, 796, 5);
angleT += 360/5;
wait(0.001); //???
}
//angleT += sin(objcount) * 8; //BOWAP- Sine makes the oscillation, * 6 ensures there are gaps.
// if-else block is here and down
if(objcount >= 240){ // A
angleT -= sin(objcount) * 8;
objcount -= 3;
}else if(objcount <= 60){ // B
angleT -= sin(objcount) * 8;
objcount += 3;
}else{ // C
angleT -= sin(objcount) * 8;
objcount += 3;
}
yield;
}
}
The main issue is that the if-else block is tested every frame (actually every sixth frame but I'll discuss that later).let obj = CreateItemU2(....);
is it possible to declare i global variable from inside a task?
also, how do i make the boss use the 'moving left' sprites when it moves left, and make the boss use the 'moving right' sprites when it moves right?
You cannot declare a global variable from within a task because when you declare a variable within a block such as a task, it cannot be accessed from outside that block.
If you want your boss to use a different set of sprites when it's moving in a different direction, first obtain the direction the boss is moving at (ObjMove_GetAngle), normalize the angle/use trigonometry to determine the direction, and use an if statement to select which sprites to use.
Can I please have an example?As rude as it may sound, but did you check the tutorials?
My scripting skills are bad :(
is it possible to declare i global variable from inside a task?Variables can only be used inside the "block" it was declared in, so no.
let x = 1; //declared a global variable "x" with the value of 1
task whatever(){
//...
x = 3; //x is now 3 and will remain 3 throughout the entire file until changed
}
I might misunderstand your question but this is how I interpreted it.
As rude as it may sound, but did you check the tutorials?
There is no such thing as "sorry to bother". Of course many people do this due to being polite.
A good question. We have exactly 0 tutorials on making stages in ph3.
Summary: A stage is created using #TouhouDanmakufu[Stage] as header. You spawn enemies within the stage and at a certain point you call the Plural script for the boss.
A set of question you need to ask yourself to tackle this is:
- Can I make a single boss attack (regular or spell card)
- Can I make a boss with multiple attacks/spellcards?
- Can I make a familiar/enemy which is NOT a boss?
- Do I understand SFX and BGM using .wav and .mp3/.ogg?
If the above is all yes, then we can tell you the rest. If not, you should tackle all of the above first.
Also this seems like a good idea for a video tutorial I think. Hmmm
I already have everything ready, I just need to put it together.Oh. Why didn't you say so :V
let idScript;
idScript = LoadScriptInThread("pathtoyourscript");
StartScript(idScript);
Oh. Why didn't you say so :V
Declare global in your stage file:Code: [Select]let idScript;
Then call anywhere during your stage this for your mid or stage boss:Code: [Select]idScript = LoadScriptInThread("pathtoyourscript");
StartScript(idScript);
The LoadScriptInThread will allow you to run a script while your stage script is still active. This can be used for any loadable scripts but in general often used for mid/stage bosses.
Enemies can be spawned anywhere during the stage. No need for specific script loading.
If you want to change music for the midboss and stage boss, you need to stop and load/play your desired song somewhere. Could be done from the boss script, plural or during a "dialogue".
How would I make everything else wait until the midboss dies?
thanks for the help, by the way
StartScript(idScript);
while(!IsCloseScript(idScript)){yield;}
I've been wondering about a thing for a while, which I didn't think of earlier.
Is there any way that the rate, at which the spellcard bonus decreases, can be influenced/changed? I'm not referring to the types of spells (e.g. survivals where the bonus doesn't decrease at all), but a place where said decrease of the bonus on normal spells can be changed. Is there one?
I kinda wanted to get back to programming Danmakufu after a while : pYes. The th_dnh.def file in your root can call to a package file to use it as a "entry point" for your game. Example from my game:
Wasn't it possible to make stand alone game in Danmakufu? Like so that you don't have to go through Danmakufu's own menus to select stages etc. and have custom main menu and stuff.
package.script.main = script/thdcs/DanceContestMain.txt
It is not the ToString function. Numbers / integers in Danmakufu are both in 0.12m and ph3 tracked as float. If you draw the X / Y position of your boss as text on your screen, you will see it as a float too.
Afaik you can use 'rtos' or 'vtos' to truncate the value and decide the number of digits as decimal. If I can find an example then I will update my post. Or you might already fix it in the mean while.
Edit:I think atoi is what you seek.
Edit2: Nope, misread the function. It isn't atoi. My apologies.
It is not the ToString function. Numbers / integers in Danmakufu are both in 0.12m and ph3 tracked as float. If you draw the X / Y position of your boss as text on your screen, you will see it as a float too.
Afaik you can use 'rtos' or 'vtos' to truncate the value and decide the number of digits as decimal. If I can find an example then I will update my post. Or you might already fix it in the mean while.
Edit:I think atoi is what you seek.
Edit2: Nope, misread the function. It isn't atoi. My apologies.
It's IntToString.
Also, more importantly, Helepolis' tutorial uses "if" and "else if" to select sprites in the spritesheet. But my spritesheet has only one animation (for idling), and i don't need the part with "else if" but if i remove it it gives me an error. Is there something else i could use instead of "if" and "else if" ?
@MainLoop{
ObjSprite2D_SetSourceRect(the name of your boss variable,insert coordinates here);
ObjSprite2D_SetDestCenter(the name of your boss variable);
}
Also is there anyone i could just chat with who knows some stuff about danmakufu ? Because i probably have tons of newbie questions and i don't really want to spam this topic
I have several sprites but they're only for idling. Helepolis used a spritesheet with movement animations and other stuff (from an official touhou game), so my problem still isn't solved :/
@MainLoop{
if(animFrame < 20) { ObjSprite2D_SetSourceRect(boss,coords); }
if(animFrame >= 20 && animFrame < 40) { ObjSprite2D_SetSourceRect(boss,coords); }
if(animFrame >= 40 && animFrame < 60) { ObjSprite2D_SetSourceRect(boss,coords); }
if(animFrame > 60) { animFrame = 0;}
animFrame ++;
}
I have several sprites but they're only for idling. Helepolis used a spritesheet with movement animations and other stuff (from an official touhou game), so my problem still isn't solved :/Sure, I'll help.
Also is there anyone i could just chat with who knows some stuff about danmakufu ? Because i probably have tons of newbie questions and i don't really want to spam this topic
Pretty much every sprite ever can be found here:
< link removed by Hele >
Just have a look around, download the sheet you need and crop out just the bit you're using. You might need to do some more editing to make it usable, Danmakufu won't handle everything for you.
Also I dug up the link for all the sound effects from all games.
< link removed by Hele >
Not sure who made this, but thanks so much.
Somebody should put this somewhere more visible.
Are those allowed? Didn't ZUN say something about touching original stuff?
first, make a variable called animframe (or whatever you feel like calling it) and set it to 0.
if (speed == 0) {
ObjRender_SetAngleXYZ(bossObj,0,0,0);
if(animFrame < 15) { ObjSprite2D_SetSourceRect(bossObj,0,0,64,117); }
if(animFrame >= 15 && animFrame < 30) { ObjSprite2D_SetSourceRect(bossObj,0,0,128,117); }
if(animFrame >= 30 && animFrame < 45) { ObjSprite2D_SetSourceRect(bossObj,0,0,192,117); }
if(animFrame >= 45) { ObjSprite2D_SetSourceRect(bossObj,0,0,256,117); }
animFrame2 = 0;
Right now i'm almost done with my animation (had to redo a spritesheet because i didn't lay the previous one out correctly so i had trouble), i'm just a bit confused about the first 2 numbers of ObjSprite2D_SetSourceRect (the 0), i looked this function up on the danmakufu wiki but it isn't very accurate and i don't get what to write there.
if (speed == 0) {
ObjRender_SetAngleXYZ(bossObj,0,0,0);
if(animFrame < 15) { ObjSprite2D_SetSourceRect(bossObj,0,0,64,117); }
if(animFrame >= 15 && animFrame < 30) { ObjSprite2D_SetSourceRect(bossObj,64,0,128,117); }
if(animFrame >= 30 && animFrame < 45) { ObjSprite2D_SetSourceRect(bossObj,128,0,192,117); }
if(animFrame >= 45) { ObjSprite2D_SetSourceRect(bossObj,192,0,256,117); }
animFrame2 = 0;
}
animFrame++; // count animFrame. (++ is +1)
animFrame2+=2; // count animFrame2.
if(animFrame > 60) { animFrame = 0; } // reset animFrame when it is higher than 60.
yield;
Technically we are not allowed to use his original resources, but it's done anyways.
However, do note that not everything that ZUN uses is his originally - sound effects and background source images in particular may come from other sources.
(I'm assuming this is the right place for this)
So I'm confused about something. I see things about the All-Star Shotsheet by Ozzy basically all over the place. I see it mentioned a lot, and used in lots of scripts, even recent ones (like, from the past couple of weeks). It certainly seems like a very good shotsheet, judging by what I've found looking through scripts' files.
But... I can't seem to actually find it anywhere.
I've certainly tried to find it. I've done searches on Google, on BulletForge, and on MotK, but I've found nothing at all; the closest I've found is the ZUN Expanded Shotsheet by Ozzy (http://www.bulletforge.org/u/ozzy/p/zun-expanded-shotsheet-for-ph3) which, while also good, doesn't give quite as much variety, and seems to just be rips of ZUN's data. I know I can just take it from other scripts, but I dunno, for some reason something about that just feels wrong, like I'm using something I'm not supposed to.
Does anybody know if there's a reason for this? Or am I just being stupid somehow? (And if I am, you're welcome to slap me.)
while(!Obj_IsDeleted(bossObj)) {
// update boss speed/dir locally
dir = ObjMove_GetAngle(bossObj);
speed = ObjMove_GetSpeed(bossObj);
// animation handling
if (speed == 0) {
ObjRender_SetAngleXYZ(bossObj,0,0,0);
if(animFrame < 15) { ObjSprite2D_SetSourceRect(bossObj,0,0,64,117); }
if(animFrame >= 15 && animFrame < 30) { ObjSprite2D_SetSourceRect(bossObj,64,0,128,117); }
if(animFrame >= 30 && animFrame < 45) { ObjSprite2D_SetSourceRect(bossObj,128,0,192,117); }
if(animFrame >= 45) { ObjSprite2D_SetSourceRect(bossObj,192,0,256,117); }
animFrame2 = 0;
}
animFrame++; // count animFrame. (++ is +1)
animFrame2+=2; // count animFrame2.
if(animFrame > 60) { animFrame = 0; } // reset animFrame when it is higher than 60.
yield;
}
}
while(!Obj_IsDeleted(bossObj)) {
// update boss speed/dir locally
dir = ObjMove_GetAngle(bossObj);
speed = ObjMove_GetSpeed(bossObj);
// animation handling
if(speed == 0){
ObjRender_SetAngleXYZ(bossObj,0,0,0);
if(animFrame < 15) { ObjSprite2D_SetSourceRect(bossObj,0,0,64,64); }
if(animFrame >= 15 && animFrame < 30) { ObjSprite2D_SetSourceRect(bossObj,64,0,128,64); }
if(animFrame >= 30 && animFrame < 45) { ObjSprite2D_SetSourceRect(bossObj,128,0,192,64); }
if(animFrame >= 45) { ObjSprite2D_SetSourceRect(bossObj,192,0,256,64); }
animFrame2 = 0;
}
else if(cos(dir) < 0){
ObjRender_SetAngleXYZ(bossObj,0,180,0); // flip vertical
if(animFrame2 < 15) { ObjSprite2D_SetSourceRect(bossObj,0,64,64,128); }
if(animFrame2 >= 15 && animFrame2 < 30) { ObjSprite2D_SetSourceRect(bossObj,64,64,128,128); }
if(animFrame2 >= 30 && animFrame2 < 45) { ObjSprite2D_SetSourceRect(bossObj,128,64,192,128); }
if(animFrame2 >= 45) { ObjSprite2D_SetSourceRect(bossObj,192,64,256,128); }
}
else if(cos(dir) > 0){
ObjRender_SetAngleXYZ(bossObj,0,180,0); // flip vertical
if(animFrame2 < 15) { ObjSprite2D_SetSourceRect(bossObj,0,128,64,192); }
if(animFrame2 >= 15 && animFrame2 < 30) { ObjSprite2D_SetSourceRect(bossObj,64,128,128,192); }
if(animFrame2 >= 30 && animFrame2 < 45) { ObjSprite2D_SetSourceRect(bossObj,128,128,192,192); }
if(animFrame2 >= 45) { ObjSprite2D_SetSourceRect(bossObj,192,128,256,192); }
}
animFrame++; // count animFrame. (++ is +1)
animFrame2+=2; // count animFrame2.
if(animFrame > 60) { animFrame = 0; } // reset animFrame when it is higher than 60.
yield;
}
}
The All Star Shotsheet was made by Ozzy/ExPorygon for a now-defunct project to create a Touhou All Stars (similar to Yuke's unreleased one). He made the shot sheet, the image containing the shots was made by gore (who must be cited).Alright, that'd explain it, thanks. (And I didn't know I have to credit gore as well; I'll keep that in mind.)
Naturally, there is not official download link to the shot sheet, because it was simply located in the collaborators folder, which was open to members of LOCAA who were working on the project. It's just that the majority of us decided that the ZUN Expanded Shotsheet was inferior and switched to the All Star Shotsheet.
Beyond this, many newer scripters have gained access to it by copying it from other scripts that use it. However, if you use it, both ExPorygon/Ozzy and gore MUST be cited, and do be aware that there are some errors in the shot sheet as well.
Thanks a looooooot ! Everything's working now !
Well, almost :
http://puu.sh/rcqmz/7cd6efe508.jpg
As you can see here there's a weird line of blue pixels on the top left corner of the sprite (of course unrelated to the background since it moves along with the sprite). I can assure you that the spritesheet does not have it. I also had this problem when i was using a single sprite. Do you know what could have caused it ? (it's not that important anyway)
Also, is it possible to disable the ugly EoSD circle thing ?
My stage isn't closing properly for some reason.Since you're not showing any code, I have to ask first: Are you actually closing the stage with CloseStgScene?
I use tasking and have SetAutoDeleteObject(true); in TFinalize, which is called at the end of TMain, which is called somewhere in @Initialize.
The music stops and the background disappears confirming the script has closed, yet the end menu doesn't pop up. Normally it just waits a few seconds but here it seems to be stuck. I can continue to move around and do whatever (so the player script is still running).
What could I have possibly done wrong?
Where did it all go wrong ?
CreateShotA1(bossX,bossY,5,10,12,30);
task fire {
let radius = 32;
let direction = 0;
let numberOfBullets = 36;
loop(numberOfBullets) {
CreateShotA1(bossX+radius*cos(direction),bossY+radius*sin(direction),5,direction,12,0);
direction += 360/numberOfBullets;
}
loop(60) { yield; }
}
radius = how far the bullets spawn from the location (in this case, the boss). 0 = in the middle of the boss.
direction = starting direction of the first bullet (before the circle is made)
numberOfBullets = how many bullets you wish to fit into this circle.
cos and sin = math. I am bad at explaining this.
That is fine if you wish to shoot things from the boundaries of the field into the field, but then beware of the Auto Delete boundary, which is by default 16 pixels on each side. So you can maximum fire at maximum 16 pixels on each side out of bounds.According to the wiki, it's not 16 pixels but 64.
SetShotAutoDeleteClip
(more informations here: http://dmf.shrinemaiden.org/wiki/Shot_Functions#SetShotAutoDeleteClip)let A = 0;
let N = 64;
loop(N){
CreateShotA1(bossX, bossY, speed, A, graphic, delay);
A += 360/N;
}
let N = 64;
ascent(i n 0..N){
CreateShotA1(bossX, boss Y, speed, i*360/N, graphic, delay);
}
Since you're not showing any code, I have to ask first: Are you actually closing the stage with CloseStgScene?It works! Doesn't look like the objects are getting deleted but the stage ends right on cue.
It works! Doesn't look like the objects are getting deleted but the stage ends right on cue.Actually, CloseStgScene is not a way to force any script end. It only closes the Stage Scene. It will tell the engine that the stage has actually ended and thus will process it all. In ph3, boss fights and stages are actually 'scenes'. You will run into these more when use plural scripts.
I've always relied on putting CloseScript(GetOwnScriptID()); at the very end, and I've never had a problem with it.
So I'm going with the assumption that CloseStgScene() is just a way to force any script to end.
If I'm making a full game I guess I'll have to switch back to CloseScript(GetOwnScriptID()); and put CloseStgScene(); somewhere in the package?
task fire {
let radius = 32;
let direction = 0;
let numberOfBullets = 36;
loop(numberOfBullets) {
CreateShotA1(bossX+radius*cos(direction),bossY+radius*sin(direction),5,direction,54,0);
CreateShotA1(bossX+radius*cos(direction),bossY+radius*sin(direction),5,direction,156,30);
direction += 360/numberOfBullets;
}
loop(60) { yield; }
}
But it keeps giving me random errors like "movement is not defined" while the exact same thing works in the first script. I couldn't spot errors like missing semi colons and stuff like that so i don't really know where it's coming from and the weird error alert system of danmakufu isn't helping :s
http://pastebin.com/LfgeDASq
Right now the two waves overlap each other. I would like to set in a way where the second wave would fire in the gap left by the first one. I tried setting direction+5 instead of just direction to try to change the angle but it didn't work i think so i don't really know how to do thisTry direction+360/(2*numberOfBullets) insted of direction for one of the bullets ;)
task fire {
let dir = AngleToPlayer;
let radius = 32;
let direction = 0;
let numberOfBullets = 36;
loop(numberOfBullets) {
CreateShotA1(bossX+radius*cos(direction+360/(2*numberOfBullets)),bossY+radius*sin(direction+360/(2*numberOfBullets)),2,direction+360/(2*numberOfBullets),54,0);
CreateShotA1(bossX+radius*cos(direction),bossY+radius*sin(direction),2,direction,156,15);
direction += 360/numberOfBullets;
}
CreateShotA1(GetPlayerX-160,GetPlayerY,3,360,318,120);
wait(60);
CreateShotA1(GetPlayerX+160,GetPlayerY,3,180,318,120);
wait(60);
CreateShotA1(bossX,bossY,3,dir,328,30);
wait(120);
loop(120) { yield; }
}
let bossname = ObjText_Create;
ObjText_SetText(bossname, "NameOfTheBoss");
ObjRender_SetPosition(bossname, 16, 12, 0);
If I do this right, it will display it in the top left corner.task spiral(offset){//Individual spiral
ascent(i in 0..30){
CreateShotA1(x,y,1.5,i*12+offset,DS_SCALE_S_WHITE,15);
yield;
}
}
task attack1{//Composite attack
ascent(i in 0..6){
spiral(i*60);
wait(15);
}
}
This would create 6 spirals beginning at different angles.GetAngleToPlayer()
. Just remember though, it's not easy on the engine, save it once to a variable called angleT
or something, recalculate it once a frame if you need to. It's much easier to fetch the value of angleT
than to recalculate using GetAngleToPlayer()
.dir
(which was set to GetAngleToPlayer()
) anywhere. If you want to aim it at the player change it to let direction = GetAngleToPlayer()
.360/(2*direction)
is redundant when you can save yourself a calculation with 180/direction
.CreateShotA1()
or any of the other shot functions. However, this can create a coloured cloud, which can fill up the entire screen. Instead you might want to create something like this:task delayBullet(x,y,s,r,g,d){//Waits before spawning a bullet with 15 frame delay, change all mentions of "15" for a different delay value
let count = 15;
if(d<15){count=d;}else{wait(d-15);}
CreateShotA1(x,y,s,r,g,15);
}
That way you don't end up with a messy cloud.let tick = 0;
while(!Obj_IsDeleted(objBoss)){
alternative(tick%180)
case(60){attack1;}
case(120){attack2;}
tick++;
yield;
}//This triggers tasks attack1 and attack2 on a 3 second cycle
I personally use timing because it keeps things more organized, but you can do the same thing in many ways.tick
or whatever you named it as a seed for pseudo-randomness. I don't know anything about the randomness but I like my attacks to be completely deterministic and consistent between runs.x^y+y^x
as a seed) add brackets and put %360
at the end.task AliceMidBoss{
let path = dir ~ "AliceBossPlural.dnh";
let scriptID = LoadScriptInThread(path);
StartScript(scriptID);
while(!IsCloseScript(scriptID)){
yield;
}
MarisaBoss;
}
task MarisaBoss{
let path = dir ~ "MarisaBossPlural.dnh";
let scriptID = LoadScriptInThread(path);
StartScript(scriptID);
while(!IsCloseScript(scriptID)){
yield;
}
}
task AliceMidBoss{
let path = dir ~ "AliceBossPlural.dnh";
let scriptID = LoadScriptInThread(path);
StartScript(scriptID);
while(!IsCloseScript(scriptID)){
MarisaBoss;
yield;
}
}
task AliceMidBoss{
let path = dir ~ "AliceBossPlural.dnh";
let scriptID = LoadScriptInThread(path);
StartScript(scriptID);
while(!IsCloseScript(scriptID)){
yield;
MarisaBoss;
}
}
Hi all,Please show us an example of a plural script as well. Plural scripts should run CloseScript(GetOwnScriptID()); once they have finished to notify the stage that it's OK to move on to the next one.
I'm working on a stage script and have encountered an issue.
I have a Midboss and Boss plurals, both of which seem to close without issue
I tested further and am now very confused.
This code:Code: [Select]task AliceMidBoss{
let path = dir ~ "AliceBossPlural.dnh";
let scriptID = LoadScriptInThread(path);
StartScript(scriptID);
while(!IsCloseScript(scriptID)){
MarisaBoss;
yield;
}
}
Crashes with an error about EnemyBossScene (presumably that it can't be created twice), which makes perfect sense.
Please show us an example of a plural script as well. Plural scripts should run CloseScript(GetOwnScriptID()); once they have finished to notify the stage that it's OK to move on to the next one.
Calling MarisaBoss every single frame means that Danmakufu will not work in general. As to why switching the yield; and MarisaBoss calls works, I personally cannot explain it.
Right now the two waves overlap each other. I would like to set in a way where the second wave would fire in the gap left by the first one. I tried setting direction+5 instead of just direction to try to change the angle but it didn't work i think so i don't really know how to do this.The way you had set it up originally is correct. What you want is making the displacement in spawn position (bossX + bla, bossY + bla) at angles offset from the first wave. Also, instead of using delay to time bullets, you should explicitly code the timing. Bullet delay should just be effect.
task fire {
let radius = 32;
let direction = 0;
let numberOfBullets = 36;
loop(numberOfBullets) {
CreateShotA1(bossX+radius*cos(direction),bossY+radius*sin(direction),5,direction,54,10);
direction += 360/numberOfBullets;
}
loop(30) { yield; }
direction = 360/(numberOfBullets*2); // or just 5
loop(numberOfBullets) {
CreateShotA1(bossX+radius*cos(direction),bossY+radius*sin(direction),5,direction,156,10);
direction += 360/numberOfBullets;
}
}
Anyway, I found a strange.. glitch? Or I don't really know what is it.You probably know Common Data is divided into Areas. When you work just using SetCommonData it uses a default Area, which is empty string. If you click on the first row in the log, the data should show up.
When I work on my package script, I can't see any CommonData in the LogWindow. Even in I create them in an active task of the package script it just don't appears. It's still existing since I can use it for condition or other stuff but it is just totally invisible on the LogWindow.
Someone have an idea about that?
This (http://pastebin.com/r8ySDWA3) is one of the two plurals.What you've posted shouldn't give you the errors you describe (besides the tests that should obviously error). I can copypaste code and have it run smoothly, so something else is going on. Please zip up your project and post it.
The other is the same (except for having different singles).
// StgTest.dnh
@MainLoop{}
You probably know Common Data is divided into Areas. When you work just using SetCommonData it uses a default Area, which is empty string. If you click on the first row in the log, the data should show up.Yes I know this. But... no. The first row is empty even if I click on it and there is no common data in the default area according the LogWindow (but actually they exist for danmakufu and they can be used).
Code: [Select]// StgTest.dnh
@MainLoop{}
:|
Yes I know this. But... no. The first row is empty even if I click on it and there is no common data in the default area according the LogWindow (but actually they exist for danmakufu and they can be used).Can you create an Area and see it? Do other packages (e.g. full games) also not log any CommonData?
It's not really an issue for the game itself but it is for debug.
// name the boss
let bossname = ObjText_Create;
ObjText_SetText(bossname, "Boss Name");
ObjText_SetFontSize(bossname,9);
ObjRender_SetPosition(bossname, 16, 12, 0);
// name a spellcard
let spellName = ObjText_Create;
ObjText_SetText(spellName, "Name of spell");
ObjText_SetFontSize(spellName,9);
ObjRender_SetPosition(bossname, 500,60, 0);
So, I've started trying out spell making, and I've ran into a little problem :You keep using bossname in the second bit instead of spellName, and an x-coordinate of 500 is outside the game field so you won't see it. Changing the first SetPosition won't do anything because the second one will overwrite it.Code: [Select]// name the boss
let bossname = ObjText_Create;
ObjText_SetText(bossname, "Boss Name");
ObjText_SetFontSize(bossname,9);
ObjRender_SetPosition(bossname, 16, 12, 0);
// name a spellcard
let spellName = ObjText_Create;
ObjText_SetText(spellName, "Name of spell");
ObjText_SetFontSize(spellName,9);
ObjRender_SetPosition(bossname, 500,60, 0);
I expected it to work but when i play the script it just shows the name of the spellcard in the top left corner. I tried random coordinates to see if it would change but nothing moved, also the boss name stops showing if there's the spell name.
if(!Obj_IsDeleted(obj)){//or whatever you named the variable
//stuff
wait(n);//insert number here
}
That way you don't get the bullets spawning in the corner.let count = 0;
while(!Obj_IsDeleted(obj)&&count<m){//replace m with the number of times you want it to loop
//stuff
count++;
wait(n);//set your own timer value
}
That way the loop breaks when the object is gone.
How do I make a player not die when they are hit? (without removing the hitbox)
// ...
ObjRender_SetScaleXYZ(playerShot,1,1,1);
task log(){
while(!Obj_IsDeleted(op_obj)){
if(ObjCol_IsIntersected(obj)) {
WriteLog("collision");
}
yield;
}
}
log();
while(!Obj_IsDeleted(op_obj)) {
// ...
https://www.youtube.com/watch?v=vsH6CfrJUzc&feature=youtu.beThis video has been marked private.
I'd tried your code with my animations and I was getting nothing, not even lasers rendering, hence why I modified my own code.If my code doesn't work drag-and-drop, and your main problem is that the laser renders (which is a Sprite) but not collides (which is a Laser object), my intuition says that either your shotsheet is incorrect or not loaded, and nothing is actually being fired. This would cause both your original problem and the problem you're finding with my code. Please make sure you can at least fire your ID 1 shot as a bullet.
Just got into learning ph3 (since programming on 0.12m has given me so much troubles) and I noticed that in the th_dnh.def file there is an option for resolution. Does this means that I can make it bigger and use higher quality images or just merely adjusts the size of the program and scales everything?
< snip >You have two options in this case:
My main problem is that music is not playing correctly when I use the plural script : if i put the music in the plural it does nothing, if i put it only in the first single it stops playing when it gets to the next single and if i put it in each single it starts playing from the beginning when it gets to the next single.Question is how you exactly put it in the plural. If you're putting it as a header, then that won't work. You'll need to separately load and play the music using the Danmakufu functions. Just like how sound effects are loaded and used, you do the same for music.
You have two options in this case:
- Use remixes, covers or rearrangements of the original songs from ZUN. But you'll need to ask permission from the artists who made those arrangements/mixes.
- Make your own rearrangement/mix/cover
Thanks ! I was putting it normally but i only used the functions in http://dmf.shrinemaiden.org/wiki/Audio_Functions and didn't know there was the Sound Object section.You can pretty much forget about the top-level Audio functions since they're very limited. They're basically just leftovers from 0.12m.
task TCircle {
let dir = GetCurrentScriptDirectory();
let countVertex = 64;
function CreatePrimRender(){
let path = dir ~ "img/lb.png";
let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP);
ObjPrim_SetVertexCount(obj, countVertex);
ObjRender_SetBlendType(obj, BLEND_ADD_RGB);
Obj_SetRenderPriority(obj, 0.60);
ObjPrim_SetTexture(obj, path);
ascent(iVert in 0..countVertex / 2) {
let left = iVert * 128;
let indexVert = iVert * 2;
ObjPrim_SetVertexUVT(obj, indexVert + 0, left, 0);
ObjPrim_SetVertexUVT(obj, indexVert + 1, left, 128);
}
let r = 120;
ascent(iVert in 0..countVertex / 2){
let indexVert = iVert * 2;
let a = 360 / (countVertex / 2 - 1) * iVert;
let vx1 = r * cos(a);
let vy1 = r * sin(a);
ObjPrim_SetVertexPosition(obj, indexVert + 0, vx1, vy1, 0);
let vx2 = r * cos(a);
let vy2 = r * sin(a);
ObjPrim_SetVertexPosition(obj, indexVert + 1, vx2, vy2, 0);
}
ObjRender_SetPosition(obj, 200, 200, 0);
}
CreatePrimRender();
}
I'm doing something wrong for sure but... I don't know what. It's almost the same thing than the magic circle, The task is well called, the path is right, The object and primitive type seems correct... I just don't know why it don't work. I'm depressed.
I'm doing something wrong for sure but... I don't know what. It's almost the same thing than the magic circle, The task is well called, the path is right, The object and primitive type seems correct... I just don't know why it don't work. I'm depressed.1. If you are using primitive objects with textures, you must use ObjSprite2D_SetDestCenter (or SetDestRect, if that's your thing).
http://pastebin.com/PuFkEQe9It's because you called attack() 3 times simultaneously without telling danmakufu to wait, so they overlap.
My boss just shoots a circle once, doesn't move at all, and then does nothing. What did i do wrong ?
Hi. I'm trying to make a circle render by using OBJ_PRIMITIVE_2D like in the default magic circle thing. I tried different things but I just can't affich it.Check out the vertex positions being set. Each pair of vertices represents a "top" and a "bottom" point, and all of these lined up makes your shape. Yet when you're positioning your vertices each top and bottom vertex are going to be set to the same position, so at best you have a 0-width circle. The reason the default system circle seemingly does this is because it uses a weird method to keep track of what radius every vertex should be at and then converts those points to where they should be in the circle. In your case all you have to do is make sure the "outside" radius is some width further out than the inside radius.
I already make it, based on the magic circle used by default in the player script
If my code doesn't work drag-and-drop, and your main problem is that the laser renders (which is a Sprite) but not collides (which is a Laser object), my intuition says that either your shotsheet is incorrect or not loaded, and nothing is actually being fired. This would cause both your original problem and the problem you're finding with my code. Please make sure you can at least fire your ID 1 shot as a bullet.
EDIT: On inspection, you had originally given your laser the shot ID=1, but in your current code you use the texture variable which will absolutely not work. ObjShot_SetGraphic requires a shot ID. The above still applies though, make sure it actually fires something at all.
Also for the log task,you haven't called itwait no you did, just in the wrong place. Note that in my blurb I define the task and then immediately call it; that's what you want. If you put it in your while loop it will keep launching new tasks every frame that each try to log on every frame, and log a billion times.
let Player = GetPlayerObjectID;
let AngleToPlayer = GetAngleToPlayer(Player);
CreateStraightLaserA1(60,110,AngleToPlayer,500,25,5,25,30);
Obj_SetRenderPriorityI(obj,21);
ObjPrim_SetTexture(obj,sbg1);
ObjRender_SetBlendType(obj,BLEND_SUBTRACT);
middle&bottom layer:Obj_SetRenderPriorityI(obj,20);
ObjPrim_SetTexture(obj,sbg2);
ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
task TWaveCircle(){
let renderTexture = GetReservedRenderTargetName(0);
let frame = 0;
let baseEffectRadius = 128;
let outerFluct = 16;
let effectRadius = 0;
let cirspd = 5;
let priEffectMin = 20;
let priEffectMax = 20;
SetInvalidRenderPriorityA1(priEffectMin, priEffectMax);
let frameWidth = GetStgFrameWidth();
let frameHeight = GetStgFrameHeight();
let frameLeft = GetStgFrameLeft();
let frameRight = frameLeft + frameWidth;
let frameTop = GetStgFrameTop();
let frameBottom = frameTop + frameHeight;
let objWave = ObjPrim_Create(OBJ_SPRITE_2D);
Obj_SetRenderPriorityI(objWave, 23);
ObjPrim_SetTexture(objWave, renderTexture);
ObjSprite2D_SetSourceRect(objWave, frameLeft, frameTop, frameRight, frameBottom);
ObjSprite2D_SetDestRect(objWave, 0, 0, frameWidth, frameHeight);
Obj_SetRenderPriorityI(objWave, priEffectMax + 1);
let pathShader = GetCurrentScriptDirectory ~ "SamplePS03_HLSL.txt";
ObjShader_SetShaderF(objWave, pathShader);
ObjShader_SetTechnique(objWave, "TecWave");
let objEnemy = GetEnemyBossObjectID[0];
while(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0){
effectRadius = baseEffectRadius + outerFluct * sin(frame*cirspd);
let enemyX = ObjMove_GetX(objEnemy);
let enemyY = ObjMove_GetY(objEnemy);
RenderToTextureA1(renderTexture, priEffectMin, priEffectMax, true);
ObjShader_SetFloat(objWave, "frame_", frame);
ObjShader_SetFloat(objWave, "enemyX_", enemyX + frameLeft);
ObjShader_SetFloat(objWave, "enemyY_", enemyY + frameTop);
ObjShader_SetFloat(objWave, "waveRadius_", effectRadius);
frame++;
yield;
}
Obj_Delete(objWave);
ClearInvalidRenderPriority();
}
Becareful with the Twave effect. I'm not sure if I don't use it badly or not but it can cause heavy FPS drops.
Anyway, i see that your circle have a nive rotation effect like in Touhou. How did you do this? I know I should use X, Y and Z angle but I can't find the exact formula to do this without having something awful.
task magiccircle(boss,type){ // draw magic circle
let obj=ObjPrim_Create(OBJ_SPRITE_2D);
let img=GetCurrentScriptDirectory()~"./MG.png";
let spin = GetCommonData("CircleSpin",0);
let s = 0;
let size = 0;
let GetBossX;
let GetBossY;
LoadTexture(img);
ObjPrim_SetTexture(obj,img);
ObjSprite2D_SetSourceRect(obj,0,0,256,256);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetScaleXYZ(obj,size,size,size);
ObjRender_SetAlpha(obj,192);
ObjRender_SetBlendType(obj,BLEND_ALPHA);
Obj_SetRenderPriorityI(obj,24);
while(!Obj_IsDeleted(boss) && !Obj_IsDeleted(obj)){
spin += 1/3;
size = GetCommonData("CircleSize",1);
ObjRender_SetAngleXYZ(obj,30*sin(spin*1.5)*type,25*cos(spin*1.5-30*sin(spin*3))*type,spin*3*type);
ObjRender_SetPosition(obj, ObjMove_GetX(boss), ObjMove_GetY(boss), 0);
ObjRender_SetScaleXYZ(obj, size, size, 0);
yield;
}
SetCommonData("CircleSpin", spin);
Obj_Delete(obj);
}
Example: magiccircle(objBoss,-1);
task ObjShader_TWaveCircle(obj){
let frame = 0;
let baseEffectRadius = 128;
let outerFluct = 16;
let effectRadius = 0;
let frameLeft = GetStgFrameLeft();
let frameTop = GetStgFrameTop();
ObjShader_SetShaderF(obj, GetCurrentScriptDirectory() ~ "SamplePS03_HLSL.txt");
ObjShader_SetTechnique(obj, "TecWave");
let objEnemy = GetEnemyBossObjectID[0];
while(!Obj_IsDeleted(objEnemy)){
effectRadius = baseEffectRadius + outerFluct * sin(frame*4);
ObjShader_SetFloat(obj, "frame_", frame);
ObjShader_SetFloat(obj, "enemyX_", ObjMove_GetX(objEnemy) + frameLeft);
ObjShader_SetFloat(obj, "enemyY_", ObjMove_GetY(objEnemy) + frameTop);
ObjShader_SetFloat(obj, "waveRadius_", effectRadius);
frame++;
yield;
}
}
My question is: I wonder if there's any method to use the TWave effect while using subtraction rendering?
Out.color = color;
return Out;
3. Add "color.a = 1;" just before "Out.color = color;"Hi. It's me again. I wondered, what kind of scripting mistake can lead to a broken replay? I know some mistakes on ComonData can do it but is there other things? Accelerating Danmakufu with Ctrl during replay can do it too or absolutly not? I try to chase the reason of all my replays issues but I'm a bit lost now..
In fact, at the begining of the script I clear all the common data to avoid any remaning common data. I think i should be enough and the script must create all common data as he should during the replay. The only common data that are saved and not cleared are the common data area where I store all the data like max score, spellcard history, ect per player and per difficulty. But these data must be updated even during the replay.
I'm not sure what kind of common data can desync the replay. I see for things like difficulty or player but how I'm supposed to do with common data that are alwas updated like spellcard score value, items value or position of a random moving boss?
Now, despite this, you can circumvent this for the most part, although it's a really shitty workaround that I hate myself for having to do. Because the actual problem is the render targets, if you need to use a fancy blend type for some texture, you can apply the shader directly to that object individually, rather than rendering your whole background to one texture and using the shader on that (which is what you should be doing). This ignores the whole purpose of using the render targets, since you never really want to apply the shader multiple times because that's stupid, but it works.
So for objects with problematic blend types you can use this to apply it per-object, but if at all possible you should be doing the usual way of rendering to a render target and using that instead.Code: [Select]task ObjShader_TWaveCircle(obj){
let frame = 0;
let baseEffectRadius = 128;
let outerFluct = 16;
let effectRadius = 0;
let frameLeft = GetStgFrameLeft();
let frameTop = GetStgFrameTop();
ObjShader_SetShaderF(obj, GetCurrentScriptDirectory() ~ "SamplePS03_HLSL.txt");
ObjShader_SetTechnique(obj, "TecWave");
let objEnemy = GetEnemyBossObjectID[0];
while(!Obj_IsDeleted(objEnemy)){
effectRadius = baseEffectRadius + outerFluct * sin(frame*4);
ObjShader_SetFloat(obj, "frame_", frame);
ObjShader_SetFloat(obj, "enemyX_", ObjMove_GetX(objEnemy) + frameLeft);
ObjShader_SetFloat(obj, "enemyY_", ObjMove_GetY(objEnemy) + frameTop);
ObjShader_SetFloat(obj, "waveRadius_", effectRadius);
frame++;
yield;
}
}
Result: http://i.imgur.com/SuUqAx5.png
As far as my knowledge on hlsl with danmakufu goes, my way of making it work is:It worked like miracle!
1. Go into the _HLSL file.
2. Find this line:Code: [Select]Out.color = color;
3. Add "color.a = 1;" just before "Out.color = color;"
return Out;
4. Done
So far, everything renders the same as when the shader is not present, but maybe I haven't found another bug yet.
Sagume's spell background is also BLEND_SUBTRACT and so far, everything looks fine.
http://imgur.com/a/pj6NU
Without the shader:
http://imgur.com/a/3pLFn
Also, is there any website or whatever that teaches how to fire basic shapes and explains the code for it ? I know how to fire a spiral and a circle but i don't know about other shapes such as lines. I could find out myself about it but it would take some time so if you guys know any place that might save me time i'll gladly take the link.
I had a lot of issues with my 0.12m framerates except I was getting massive frames on the start menu too.
I tried this (http://enbdev.com/download_convertor_dx8todx9.htm)and it's worked fine for me, maybe it will be of use to you too?
task EffectTrail1(shot, graphic, frame, blend){
while(!Obj_IsDeleted(shot)){
CreateEffTrail1(shot, graphic, blend);
wait(frame);
}
}
task CreateEffTrail1(shot, graphic, blend){
let rect = GetShotDataInfoA1(graphic, TARGET_ENEMY, INFO_RECT);
let eff = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(eff, "./resource/shot/Shot/ZUNShot.png");
ObjSprite2D_SetSourceRect(eff, rect[0], rect[1], rect[2], rect[3]);
ObjSprite2D_SetDestCenter(eff);
ObjRender_SetPosition(eff, ObjMove_GetX(shot), ObjMove_GetY(shot), 0);
ObjRender_SetAngleZ(eff, ObjMove_GetAngle(shot)+90);
ObjRender_SetBlendType(eff, blend);
let alpha = 100;
while(!Obj_IsDeleted(shot)){
ObjRender_SetAlpha(eff, alpha);
ObjRender_SetAngleZ(eff, ObjMove_GetAngle(shot)+90);
alpha-=5;
if(alpha <= 0){
Obj_Delete(eff);
}
yield;
}
Obj_Delete(eff);
}
Is there a way to optimize this trail effect, so that it doesn't completely lag the game whenever there's a large amount of bullets on the screen?
Actually, now that I think about it, it's reasonable. If 200 bullets are present on the screen, and "frame" is set to 6, that's already 1200 graphics the game has to render.
task Task1() {
loop{
do_stuff;
yield;
}
}
running aside tasks like:task Task1() {
loop{
yield;
do_stuff;
}
}
What this does is create a render target for each "frame" of the effect, and an object associated with that texture. Every step, one render target reproduces the current bullets on screen, and each of the textures gradually fade out. When they reach the end of the cycle they instead take the place as the "lead".
Unfortunately due to how render targets work, you can't only use one render target, as when a render target texture is assigned to an object, if the render target is updated the object reflects that. Any objects using it as a texture just look at that chunk of memory to see what to draw, which makes sense. Also unfortunately, as many people know, you cannot use non-integer drawing layers without huge bugs. Because of this, you can either have every texture on the same layer, which causes some visual hiccups due to the draw ordering, or you can try putting each texture on descending layers (see the commented-out bit), which is visually better but can interfere with the rest of the game if the effect spans too many layers. That being said, this is definitely viable in terms of efficiency, I think.
Also here's one clumsy solution for the bullet trail effect.I'm really intrigued by this effect. Do you think that this would be effective at creating a motion blur effect? I'm thinking of 0.12m's SetEffectForZeroLife function that had a motion blur effect as one of the things it could do.
It depends how deep you want the motion blur to go, probably. This works because it copies only layer 50 (i.e. bullets) and draws immediately underneath it, so it aims to still draw over everything that would be drawn below bullets. If you wanted to have the effect covering many layers you'd have to draw the effect under all those layers and make sure it doesn't bork.Ah yes, shaders, the one thing I may never really get how to use well. Yeah, it would be cheap, fake motion blur in this way. It just an idea that I had. What I'd give for a basic shaders tutorial for Danmakufu.
It also isn't really motion blur at all because a real motion blur is an interpolated effect, not just the texture at several positions. If an object moves four pixels in one frame you'd still have to fill that gap somehow. It might still look fine though.
Honestly the real solution here is probably shaders. I used render targets because I figured it might work and I wanted to see how it could be done.
Okay so I turned it into a full motion blur. It does look pretty cool and is definitely usable as long as you follow the layer constraints. In this case there shouldn't be anything from layers (79-n) to 79.I will indeed. I'll try to make a SetEffectForZeroLife like function and try it out in my game, EUB, if I have your permission to include it.
pls test
Please use Pastebin for your code.
Additionally, this task does not include enough information for us to determine what's going wrong. There's a lot of purging textures from memory, but nowhere in the code posted do you actually load anything.
If you have issues with bullets going missing and other graphics not showing up (the wording suggests that the bullet GRAPHICS disappear, but the bullets themselves are still collidable? Please clarify), please show us some of that code.
let dankCutin = 'insert file path here';
task LoadImages
{
LoadTexture(dankCutin);
}
A lot of the problems might disappear if you actually organize your bosses into individual plural scripts and use a stage to link them all together.
task fire{
let angleT = 0;
let dir = angleToPlayer;
GetPlayerState;
loop(10){
let objBullet = CreateShotA2(bossX,bossY,2,angleT,-0.05,0,40,10);
BulletCommands(objBullet);
angleT+=360/10
}
task BulletCommands(objBullet){
while(ObjMove_GetSpeed(objBullet) > 0) {yield;}
wait(60);
let angleT = rand(0,360);
loop(10){
CreateShotA1(ObjMove_GetX(objBullet),ObjMove_GetY(objBullet),2,angleT+(rand(-4,4,)*angleT),rand(33,39),10);
angleT += 360/10
}
Obj_Delete(objBullet);
}
}
I'm having a problem with (0,0) spawning after a player death. I've looked on Sparen's tutorials and saw his code and how to fix it, but his fixes (0,0) after boss death (at least that's what I understood. I'm still really new to this lol).
Your problem lies within the bullets themselves. Nothing to do with the boss or player. Problem: You're spawning new bullets based on the position of the old bullet (example: the original before exploding).
Let us call the first bullets, before they explode, the master bullet. The child bullets are spawned based on the XY location of their master. When a player dies, it will clear out all the bullets on the screen (by default). If the master bullet is gone, there will be no XY coordinate available for the child bullet to know. And therefore, it will automatically spawn at 0,0.
I didn't think of that. Thanks! I'll be sure to try that out. Please can you give me a short example though?http://pastebin.com/Lnrvf44V
Thank you so much for your help!! I think I figured it out. If you have another way, I'd love to see it as well.Ah, you figured it out with the easiest and most effective solution.
Thank you so much for the hints. They really helped!! All I added in "task BulletCommands(objBullet)" was "if(Obj_IsDeleted(objBullet)) {return;}" and it seems to work perfectly. Again thank you so much!!
@DumbFakeShit {
}
To your code and Danmakufu won't even complain for one bit.This shouldn't break anything, but it's generally considered to bad.Actually, nothing is considered bad. Both relative and absolute pathing are fine to use. It is up to the programmer to deal with it correctly. While it is true that renaming would cause things to break, it has nothing to do with releasing to the internet as if you ship the entire structure. The downloader just has to unpack it inside the script directory. He/she shouldn't touch the folder structure or names, obviously.
This is because if, for example, you moved or renamed the Stage Test folder,
or released it onto the internet, every "script/Stage Test/<path>" would have to be changed manually
if(GetPlayerState == STATE_DOWN && GetPlayerLife == 0 && GetCommonData("remainingContinue", 0) > 0) {
SetPlayerLife(3);
}
Because technically you're on your last life. Validating it at -1 is non existent, because STATE_END will kick in.So what do I do? Add +1 life, adjust the HUD so if you're at 1 life, it shows 0 hearts?Yes, actually. That is the only way I managed to make it work. In my experiments, once STATE_END was triggered there was no stopping it.
Yes, actually. That is the only way I managed to make it work. In my experiments, once STATE_END was triggered there was no stopping it.Check. If that is the case, then we have no choice.
Short answer: No, by default objects are NOT autodeleted when they leave the screen.
Longer answer: Do you have the console log window open while testing? The log window can be activated through the config.exe by ticking the box for it. It will show info about number of bullets, objects, tasks running etc.
// leave field == delete
if(ObjMove_GetX(obj) < GetClipMinX-17 || ObjMove_GetX(obj) > GetClipMaxX+17 || ObjMove_GetY(obj) < GetClipMinY-17 || ObjMove_GetY(obj) > GetClipMaxY+17) {
Obj_Delete(obj);
}
function SetUpBGM(bgmpath, loopStart, loopEnd) {
let obj = ObjSound_Create();
ObjSound_Load(obj, bgmpath);
ObjSound_SetSoundDivision(obj, SOUND_BGM);
ObjSound_SetLoopEnable(obj, true);
ObjSound_SetLoopTime(obj, loopStart, loopEnd);
return obj;
}
let bgmpath = GetCurrentScriptDirectory() ~ "/sound/bgm.ogg";
let bgmObj = SetUpBGM(bgmpath, 13.6, 177.2);
ObjSound_Play(bgmObj);
function SetUpSoundEffect(soundpath, volume) {
let obj = ObjSound_Create();
ObjSound_Load(obj, soundpath);
ObjSound_SetSoundDivision(obj, SOUND_SE);
if (volume > 0) {
ObjSound_SetVolumeRate(obj, volume);
}
return obj;
}
let moveStarSoundPath = "script/experimentation/Sanae/sound/bulletmove.wav";
let moveSoundObj = SetUpSoundEffect(moveStarSoundPath, 35);
ObjSound_Play(moveSoundObj);
ObjEnemyBossScene_StartSpell(objScene);
While I'm here, though, how does render priority on bullets work? I tried Obj_SetRenderPriorityI(bullet, <priority>) and setting it to 80+ caused them to render out of place as expected (i.e. treating the top left of the window as 0,0 rather than the top left of the playing area) but bullets with an ostensibly lower render priority were appearing on top of bullets with a higher one. Is there some trick I need to be aware of?Higher priority -> drawn on top. Meanwhile stuff under 20 and over 80 uses the window for the origin, while stuff in 20~80 uses the STG frame. Within the same priority, whatever starts drawing later is drawn on top. I'm not sure of the circumstances you're talking about but any object will behave the same way.
And actually, come to think of it, I have another question...whenever I try to use GetCurrentScriptDirectory() for a #include, Danmakufu crashes. This is irritating because it means all my includes are full filepaths rather than being flexible based on where the script folder is (and I'm trying to separate out things like essential functions and animation data into a separate code file that I can just include in each script). Is there any remedy for this?You need to be aware that there's a difference between the script's main interpretation stage and the pre-processing stage(s). Most of the #Stuff headers are read way in advance for use in the script select menu, but when you open the script there's a pre-processing stage that glues all the #includes together and checks for errors and whatnot. This isn't a place where you can put code, it just reads the path you provide and pastes that script into the current one at that line. To get relative paths you use . to reference current directory and .. for the parent directory, so if in the same folder you have bla.dnh you use #include "./bla.dnh", and if there's a lib folder above the script's folder with a lib_anim.dnh file you'd use #include "../lib/lib_anim.dnh".
ascent(j in 0..20) {
//Fill up shots array here
Obj_SetRenderPriorityI(shots[j], 50);
}
ascent(j in 0..20) {
//Fill up shots array here
Obj_SetRenderPriorityI(shots2[j], 55);
}
shots in the first array are still appearing over the top of shots in the second array if they were spawned earlier, as though their priorities were identical. The shot arrays are generated in a task which takes a render priority value as an argument (the code above shows the numbers for the sake of clarity) and passes it directly on to each shot generated using the function above.Yeah I'm not too sure why that would be the case. I would suspect that the function isn't actually being applied to the objects, but if you can use your method to make them 80+ then that's not the case.
task bla(g,p){
let shots = [-1,-1,-1,-1,-1];
ascent(i in 0..5){
shots[i] = CreateShotA1(192, 100, 2, 90, g, 0);
Obj_SetRenderPriorityI(shots[i], p);
}
}
bla(SHOT_AMULET_RED, 50);
yield;
bla(SHOT_AMULET_BLUE, 55);
Question about arrays: Was there a function to quickly check whether an Object or value is within the array or do I have to check that manually myself with a loop through the Array?Without any other data structures that are more appropriate for contains checks, or other special properties to the data that would make it easier (e.g. the array is already sorted, in which case you can binary search (https://en.wikipedia.org/wiki/Binary_search_algorithm)) you're going to have to go through it all.
#TouhouDanmakufu[Single]
#ScriptVersion[3] //This is required for ph3 scripts
#Title["Border of cliche and beginner"]
#Text["SampleA01:Shooting Bullets Straight Down"]
#BGM ["./LLS - Alice Maestra.mp3"]
//Danmakufu basic has dimensions 384 x 448
//Load the default shotsheet
#include"script/default_system/Default_ShotConst.txt"
#incluce"script/default_system/Extra_ShotConst.txt"
task MainTask{
BoWaP
}
task BoWaP{
let angleT = rand(0, 360);
let objcount = 0;
while (ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){
CreateShotA1(102, 134, 3, angleT, 1, 5);
CreateShotA1(282, 134, 3, angleT, 601, 5);
angleT += sin(objcount) * 12; //BOWAP
objcount += 1;
yield;
}
}
'lo everyone. Newcomer here. I've been toying with the creation of some basic patterns, but I'm finding myself stuck on two problems that I can't seem to figure out.
The first is the creation of prefight chatter. While I've managed to display text with ObjText, managed to create image overlays of those speaking, and even creating semi-transparent pictures, I'm still not sure how to put all of this together into one single smooth system for talking. If anyone could tell me how to do this, I'd be grateful.
The second question is related to creating my own bullets. I've created some cuttlefish shaped bullets on a .png file. However, when I try to use them in a pattern, the bullets don't fire at all. If I change the bullet ID to one of the default shots, it fires just fine, so the problem isn't with firing the bullet in the first place.
The pastebin for my shots are here.
http://pastebin.com/fEc2xZgE (http://pastebin.com/fEc2xZgE)
Shot constant sheet is here.
http://pastebin.com/cg7QQKzq (http://pastebin.com/cg7QQKzq)
And the shot single file is here.
http://pastebin.com/xP3XJyKX (http://pastebin.com/xP3XJyKX)
Nah, all that's fine. The load function is just called in the constants file (calling it in the script scope happens to be acceptable). The problem is just
#incluce"script/default_system/Extra_ShotConst.txt"
Nah, all that's fine. The load function is just called in the constants file (calling it in the script scope happens to be acceptable). The problem is justThank you. I can't believe I never saw that fault myself. Now I've got the shot sheet working, which means that I am that much closer to finishing my work. Again, thanks for your help.
#incluce"script/default_system/Extra_ShotConst.txt"
function bulletLine(x1, y1, x2, y2, n){
let dx = (x2 - x1) / (n - 1);
let dy = (y2 - y1) / (n - 1);
ascent(i in 0..n){
bullet(x1 + i*dx, y1 + i*dy); // your bullet here
}
}
function star(x, y, r, n){
ascent(i in 0..5){
let x1 = x + r * cos(i * 360/5);
let y1 = y + r * sin(i * 360/5);
let x2 = x + r * cos((i+2) * 360/5);
let y2 = y + r * sin((i+2) * 360/5);
bulletLine(x1, y1, x2, y2, n);
}
}
It doesn't "require" trig, but using a bit to know where the star's points are is a good idea. Once you have that, you would just spawn lines of bullets from point A to B, which can be done with the following:Code: [Select]function bulletLine(x1, y1, x2, y2, n){
let dx = (x2 - x1) / (n - 1);
let dy = (y2 - y1) / (n - 1);
ascent(i in 0..n){
bullet(x1 + i*dx, y1 + i*dy); // your bullet here
}
}
The n is the number of bullets spawned. For a star with radius r (the distance from center to the points) the point at angle t is going to be (r * cos(t), r * sin(t)). Then you want to draw lines between each point and the point two after it (going clockwise). You end up with this:Code: [Select]function star(x, y, r, n){
ascent(i in 0..5){
let x1 = x + r * cos(i * 360/5);
let y1 = y + r * sin(i * 360/5);
let x2 = x + r * cos((i+2) * 360/5);
let y2 = y + r * sin((i+2) * 360/5);
bulletLine(x1, y1, x2, y2, n);
}
}
function someFunction(number) {
let obj = CreateObj(etc...
let value = number;
<drawing stuff>
return obj;
}
let someObject = someFunction(1);
// Somewhere I want to retrieve that value and modify it.
I wanted to know if it is possible to have a texture or png work as a clipping mask like you would have in image editing software? what I'm looking to do is have part of the background be see through and open up to a separately scrolling layer however I also have a pattern on top that covers the blank space I am looking to make, any suggestions?You can, but it requires the use of shaders. Fortunately alpha masks are one of the official samples you already have (SamplePS02) and it should work with minimal tweaking, but in order to have the scrolling behaviour you want you will need to do significantly more work, either by doing some extra shader programming or by using render targets and using the resulting texture as the mask.
function returnArray(one, two, three) {
return [one, two, three]; //Return array of value with same type or different type?
}
function returnObj() {
let data = //Somehow create an object that store value?
/*
Like this? (C++, C#, ...)
struct {
int testOne;
bool testTwo;
};
*/
return data; //And return it?
}
function wait(time) { //Basic yield
loop (time) {
yield;
}
}
//Wait inside another function
function test() {
wait(45);
}
//Calling test
test(); //What is the behavior now? Pause the script file for 45 frame or what else?
Dump question, but can I do these thing?Code: [Select]function returnArray(one, two, three) {
return [one, two, three]; //Return array of value with same type or different type?
}
function returnObj() {
let data = //Somehow create an object that store value?
/*
Like this? (C++, C#, ...)
struct {
int testOne;
bool testTwo;
};
*/
return data; //And return it?
}
Neither of them are possible. For the latter, you will have to assign object values to another type of object.
Tutorial on things that you said? Need to read more on it.
And after a look on wiki, I saw CommonData, is that the same as struct, or different, but same, but different, or Obj_SetValue and Obj_GetValue?
Also, I wonder what the data type of Obj ID? String or what?
Obj_SetValue and Obj_GetValue are used to store custom fields in objects.
The data of object IDs are integers, I think. Usually you refer to the variable referring to an object and pass that in as a parameter.
let bla = ObjShot_Create(OBJ_SHOT);
Obj_SetValue(bla, "_name", "ghost");
Obj_SetValue(bla, "_hp", 8);
Obj_SetValue(bla, "_attack", 2);
Obj_SetValue(bla, "_pos", [0,0]);
There are a lot of predefined variables. I could list most of them but I don't know why you'd need a list of them in the first place; the documentation will list them when necessary.
I need those because I'm currently making a complier for danmakufu (not sure when It will done) on the web so if you can list those I really appreciated :)
Also include variable that scripter can't modify like GetCurrentScriptDirectory?
Reserved Keywords: https://sparen.github.io/ph3tutorials/ph3u1l5.html#sub9
Functions: http://dmf.shrinemaiden.org/wiki/Functions_(ph3)
Does somebody knows, if "Blender" can work like "Metasequoa" making 3D objects?
Blender is a 3D modeling tool, and you can export Blender projects to DNH-compatible formats.
Hooray! But how can I do it? I tried each format, but it didn't work: .3ds .abc .blend .dae .fbx .mtl .obj .ply .stl .x3d
At first I have always done it with Metasequoa. With .mqo formats.
I've been lost on the scrolling background with scrolling cutouts a while. I've looked into shaders and create render target but haven't gotten either to work, so what exactly am I missing?It's complicated. If you wanted to use pure shaders, you'd have to write a shader technique that uses a variable to set the position of the texture before it's applied. But that may or may not be more difficult than an alternative.
/*----------------
Mask object, for applying alpha masks to specific drawing layers.
Is a 2D Sprite object and requires manual setup of texture and rects.
Applies mask on layers from `layer_min` to `layer_max`.
-----------------*/
function ObjMask_Create(layer_min, layer_max){
let objMask = ObjPrim_Create(OBJ_SPRITE_2D);
// set up render target
CreateRenderTarget("tex_mask");
// set up shader
let mask = ObjShader_Create();
ObjShader_SetShaderF(mask, GetCurrentScriptDirectory() ~ "SamplePS02_HLSL.txt");
ObjShader_SetTechnique(mask, "TecMask");
ObjShader_SetTexture(mask, "textureMask_", "tex_mask");
SetShaderI(mask, layer_min, layer_max);
task run(){
while(!Obj_IsDeleted(objMask)){
// make visible when drawing to render target
ObjRender_SetAlpha(objMask, 255);
RenderToTextureB1("tex_mask", objMask, true);
// otherwise invisible
ObjRender_SetAlpha(objMask, 0);
yield;
}
Obj_Delete(mask);
RemoveTexture("tex_mask");
}
run();
return objMask;
}
let mask = ObjMask_Create(26, 28); // applies to layers 26~28
ObjPrim_SetTexture(mask, GetCurrentScriptDirectory() ~ "mask.png");
ObjSprite2D_SetSourceRect(mask, 0, 0, 1024, 1024); // looped texture for scrolling
ObjSprite2D_SetDestCenter(mask);
let x = 0;
let y = 0;
loop{
// scroll texture
ObjRender_SetPosition(mask, x, y, 0);
x = (x + 1) % 512;
y = (y + 1) % 256;
yield;
}
There's a plugin for .mqo export somewhere.
More newbie questions from me. Does ph3 have a function for creating armour for a boss? That is, cut the incoming damage a boss takes from shots by a set number? As I understand it, you can use ObjEnemy_SetDamageRate to set a percentage of damage taken from bombs and bullets. But it's not percentage I'm looking for. I want a flat rate, so that an attack with few but high-powered hits will be more effective than an attack with many low-powered hits.This seems kind of silly conceptually. Shmups have gone forever without needing this, since it generally comes down to the fact that focused shots are balanced so they cover a narrow area but deal a lot of damage, while spread shots are balanced so they cover a wide area but deal relatively less damage, that is mitigated by having more shots hit. If the difference is instead about the low-powered shots having a high number of hits per second, then just give the "strong" shot more damage or reduce the hit rate of the other shot. Asking for an explicit balancing override seems to ignore the point, but if you really want to you can always set different damage rates based on reading which player it is with GetPlayerID.
Second. Is there a way to link a boss HP to the stats of their familiars? That is, the boss herself is immune to all damage, but as you destroy familiars, the boss takes damage until she reaches 0 HP. I suppose it's possible through the use of ObjEnemy_AddLife, but will that work on a survival spell? And if so, is it possible to change the upcoming spellcard depending on if the spellcard was beaten by timeout or by defeating familiars?The former is definitely possible just as you think. The latter is a bit more complicated, but it basically amounts to having the single script run different tasks (with the actual contents) based on CommonData (not recommended) or setting an object value with Obj_SetValue on the boss scene object during the script before, and reading it on the relevant script.
Second. Is there a way to link a boss HP to the stats of their familiars? That is, the boss herself is immune to all damage, but as you destroy familiars, the boss takes damage until she reaches 0 HP. I suppose it's possible through the use of ObjEnemy_AddLife, but will that work on a survival spell? And if so, is it possible to change the upcoming spellcard depending on if the spellcard was beaten by timeout or by defeating familiars?
// Test damage for dual partners obj = main boss obj2 = partner.
task shareLifeHandler(obj, obj2) {
// get the HP of the main and store it in var
let mainBossHP = ObjEnemy_GetInfo(obj, INFO_LIFE);
// Set the HP for the partner.
ObjEnemy_SetLife(obj2, mainBossHP);
while(!Obj_IsDeleted(obj)) {
// Only update the HP of the boss if it actually gets hit. This is to prevent the HP from snapping to the main value.
if(ObjEnemy_GetInfo(obj2,INFO_SHOT_HIT_COUNT) > 0) {
ObjEnemy_SetLife(obj, ObjEnemy_GetInfo(obj2, INFO_LIFE));
}
// update the HP of the partner continously from the main (shared HP)
ObjEnemy_SetLife(obj2, ObjEnemy_GetInfo(obj, INFO_LIFE));
yield;
}
}
array = [
[card1, card2, ..., card10],
[card11, card12, card13]
];
let cardsInPageArray = [];
totalPages = 0;
let index = 1;
let temporaryArray = [];
ascent(i in 0..totalPages) {
ascent(j in 0..numberOfCards) {
let setText = "Spell Card " ~ IntToString(index);
let textObject = writeGraphicalText(160, 100 + (j*22), 255, 17, [255,255,255], [255,255,255], [42,99,122], 512, setText);
temporaryArray = temporaryArray ~ [textObject];
index++;
}
cardsInPageArray = cardsInPageArray ~ [temporaryArray];
}
Stage 1
└ Page 1
└ Card 1, [...], Card 5
Stage 2
├ Page 1
│ └ Card 1, [...], Card 10
└ Page 2
└ Card 11, Card 12, Card 13
Stage 3
├ Page 1
│ └ Card 1, [...], Card 10
├ Page 2
│ └ Card 11, [...], Card 20
└ Page 3
└ Card 21, [...], Card 24
#include"script/TestNiko/Scripts/Res.txt"
task timer{
if(GetTimer == 10){
PlaySE(To);
wait(60);
}
if(GetTimer == 0){
StopSE(To);
}
}
task timer(){
loop{
if(GetTimer < 10){
PlaySE(To);
}
wait(60);
}
}
task stage{
Wait(120);
CreateEventFromScript(GetCurrentScriptDirectory ~ "Evnt1.txt");
CreateEnemyBossFromFile(GetCurrentScriptDirectory~"Plural.txt", 0, 0, 0, 0, 0);
Wait(60);
Clear;
}
script_enemy_main{
// stuff
CreateEventFromScript("EventName");
// stuff
}
script_event EventName{
// event
}
Help!
When I launch a STG threw a PACKAGE script AND when I press PAUSE, it comes to a black screen. However when I launch this STG alone, all is working properly. Which reason is possible for that? (P. S. reason is 100% not in Pause System).
Thanks in advance!!
(P. S. reason is 100% not in Pause System).You can NEVER, EVER be 100% sure of this. As a game dev, you should know better than to assume that 'X is definitely not the problem'. Oftentimes, you overlook the actual problem when you approach it like this.
Ok. I try one more time.
There are a full stage and a package script (menu). If I open just a stage script, all works properly. BUT if I open this stage script within the package script and try to run PAUSE SCENE during playing stage it comes to black screen.
I tried to insert other PUASE SCENEs. But problem didn't change. So, I thought that the problem is surely not in the PAUSE SCENE itself.
Question: Possible reasons for that?
//in package stage scene main loop
if(GetVirtualKeyState(VK_PAUSE) == KEY_PUSH) {
let resPause = RunPauseScene();
alternative(resPause)
case(RESULT_RETRY) {
//Checking what to do
if(!IsReplay()) {
//Retry
TerminateStageScene();
TStageScene("");
return;
} else {
TerminateStageScene();
TStageScene(pathReplay);
return;
}
} case(RESULT_END) {
TerminateStageScene();
}
}
...
function RunPauseScene() {
RenderSceneToTransitionTexture();
PauseStageScene(true);
let pathScript = GetCurrentScriptDirectory() ~ "system/Pause.dnh";
//Starting pause script and stuff
let idScript = LoadScript(pathScript);
StartScript(idScript);
while(!IsCloseScript(idScript)) {
yield;
}
PauseStageScene(false);
let res = GetScriptResult(idScript);
return res;
}
else{
TerminateStageScene();
TStageScene(pathReplay);
return;
}
I need a bit more details on this, I can vaguely remember I had a similar issue with my setup. How exactly are you starting your boss music or your stage music?
@Event
...
case(EV_PAUSE_ENTER){
ObjSound_SetRestartEnable(music, true);
ObjSound_Stop(music);
}
case(EV_PAUSE_LEAVE){
ObjSound_Play(music);
ObjSound_SetRestartEnable(music, false);
}
...
// When the script is booted
StopMusic(GetAreaCommonData("sound", "song", 0));
PlayMusic(BGM_PAUSE);
case(PSE_CANCEL) {
. . .
PlayMusic(GetAreaCommonData("sound", "song", 0));
. . .
}
// before closing the script
StopMusic(BGM_PAUSE);
I have a weird question, I'm back to using PH3 again, and was wondering something, does ph3 have it's own function for conversation between characters? Or do you have to make your own?
@HelepolisSorry for being unable to respond on time. Lately been quite busy that I even neglected my own game development.
I tried to do sound system as u said, but it was way too complicated for me. Could u tell me please how it works more detailed. And how can I put these variables into a AreaCommonData???
Edit: Nevermind, i solved the problem :/
Curious though, what was the final problem and how did you solve it?
ObjSound_SetRestartEnable( GetAreaCommonData("sound", "song", 0) ,false)
Which is of course wrong, because this common data not a music object itself. The solution was to call this function as I did it with play/stop music object.
task fireRed() { }
task fireBlue() { }
task fireGreen() { }
I have no idea how to run three scripts simultaneously.You can actually use LoadScript and StartScript to start any number of scripts. I actually do this to start special scripts for effect rendering and sound management in my game. They listen for Event signals from other scripts to perform visual effects like concentrations and explosions and play sound effects without worrying about being interrupted by the ending of a single script.
Edit3:My guess was that each new script was actually a task of sorts running from the hidden 'true' MainLoop. The hidden MainLoop would yield to the new script's MainLoop which would then in turn yield to any running tasks in that script. This begs the question of whether I can have coroutines start other coroutines which is something I had not considered.
Wow, I forgot to answer your question after building up this much of a wall of text. I can only guess the following:
The Danmakufu Engine launches a new thread for every new script started. When you have a Stage Script and a Spell Card script, they are both independent instances, but the Engine's main thread is aware. Each script also launches its own routine called the @MainLoop, which has highest priority unless yielded within the script.
Scripts themselves don't conflict over each other's @MainLoop, that is for sure. But the execution of which script's MainLoop is most likely controlled by the Engine's main thread.
ObjSound_SetLoopSampleCount
What means one sample count, and how can I measure it?Could somebody help me please to understand this functionSample count you can measure using for example Audacity. See this screenshot:Code: [Select]ObjSound_SetLoopSampleCount
What means one sample count, and how can I measure it?
Many thanks in advance!
ObjSound_SetLoopSampleCount(<object>, 647932, 1479241);
task TimeCheck{
while(ObjEnemyBossScene_GetInfo(bossObj,INFO_TIMER)<=10){
TimerOut;
wait(60);
}
}
It would countdown endlessly, even before it got to 10. I've tried it in an if statement, and in the mainloop, but it wasn't working, oh well... while(ObjEnemyBossScene_GetInfo(bossObj,INFO_TIMER)>=10)
So, just see what was happening, or to see if it was the path. But the path was fine... Except, it wouldn't countdown at all. if(ObjMove_GetY(obj)<10){Obj_Delete(obj);}
task TimeCheck{
while(ObjEnemyBossScene_GetInfo(scene, INFO_TIMER) >= 10){
yield;
}
while(ObjEnemyBossScene_GetInfo(scene, INFO_TIMER) < 10){
TimerOut;
wait(60);
}
}
Except if you only need to check every second to see if it's under 10, swapping that yield for another wait(60) is a better idea.what is the code that calls TimeCheck()?I put in in different places, but the code in written in a library, and I tried to call it in another code in the library that render's the boss's sprite, instead I made another task in the library "DoAll", and put in all the initialize of the singles. (The point of DoAll is to have a control of every Initialize script that applies to every single without having to change EVERY script), I only have TimeCheck; in it right now.
task DoAll{
TimeCheck;
}
and yes, I'm trying to make the graphic of the effect delete at the top in case it's not deleting at all and is accumulating.I need to see more of the spellcard effect in order to see what you're actually telling it to do.
task SpellGraphic(frames,amount){
let frame = 0;
loop(frames){
if(frame==amount){
BEAMs;
frame=0;
}
frame++;
yield;
}
}
task BEAMs{
let r = rand(100,300);
let X = rand(0,2);
let movex = rand(-1,1);
let movexx = 0;
let move = 0;
let xx = GetPlayerX;
let yy = GetPlayerY-dist;
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj,SpellBall);
Obj_SetRenderPriorityI(obj,40);
ObjRender_SetBlendType(obj,BLEND_ADD_RGB);
ObjRender_SetAngleXYZ(obj,0,0,0);
ObjRender_SetColor(obj,50,150,225);
ObjSprite2D_SetSourceRect(obj,0,0,100,100);
ObjSprite2D_SetDestRect(obj,-50,-50,50,50);
ObjRender_SetPosition(obj,GetPlayerX,GetPlayerY,0);
while(!Obj_IsDeleted(obj)){
ObjRender_SetPosition(obj,xx+movexx,yy,0);
ObjRender_SetScaleXYZ(obj,X,X,0);
yy-=15;
movexx+=movex;
X+=0.01;
if(ObjMove_GetY(obj)<10){Obj_Delete(obj);}
yield;
}
}
task SpellGraphic(num, amount){ // number of loops instead of frames
loop(num){
wait(amount);
BEAMs;
}
}
#UserItemData
item_image = "./filename.png"
ItemData{ //...
item_image is not a "variable" because item data sheets aren't scripts to be executed; they're more like configuration files. item_image already has a predefined meaning and the program just checks for the line that says it.
Which should reveal what the problem is. You can't just plop GetCurrentScriptDirectory() in there because it isn't a script to be executed. The text "GetCurrentScriptDirectory()" makes no sense there. It should be something likeCode: [Select]#UserItemData
item_image = "./filename.png"
ItemData{ //...
In filesystems a single dot . refers to the current directory and two .. refers to the parent directory.
task CircleShoot2{
wait(120);
let angleT=0;
let phase=0;
if(phase < 3){
loop{
loop(20){
ascent(i in -2..2){
let shot2 = CreateShotA1(ObjMove_GetX(objBoss) + 30 * sin(angleT), ObjMove_GetY(objBoss) + 30 * cos(angleT), 3, GetAngleToPlayer(objBoss) + i * 20 + 10 , 136, 5);
}
angleT += 360/20;
}
phase++;
wait(45);
yield;
}
}
if(phase >= 3){
loop{
loop(20){
ascent(i in -2..2){
let shot3 = CreateShotA1(ObjMove_GetX(objBoss) + 30 * sin(angleT), ObjMove_GetY(objBoss) + 30 * cos(angleT), 2, GetAngleToPlayer(objBoss) + i * 20 + 10 , 183, 5);
}
angleT += 360/20;
}
phase = 0;
wait(45);
yield;
}
}
}
loop {}
never terminates until you forcefully make it exit via break; or return; I suggest using a while statement.while (phase < 3) {/* code */ phase ++;}
Code: [Select]loop {}
never terminates until you forcefully make it exit via break; or return; I suggest using a while statement.
e.g.Code: [Select]while (phase < 3) {/* code */ phase ++;}
let speed = 1;
ascent(i in 0..9){
CreateShotA1( -, -, speed, 45 + i*10, -, -);
}
Could just use if statements, but speed = floor(i/3)+1 should do it.
ascent(iObj in 0..9){
ObjRender_SetX(obj, 508 + iObj*10 + floor((iObj)/3)*6);
...
}
task Shoot{
wait(120);
let AngleTRed = 45;
let AngleTBlue = 135;
loop{
let objShotRed = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 3, AngleTRed, BUBBLE_RED, 5);
AngleTRed += rand(85,90);
Reflect(objShotRed);
let objShotBlue = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 3, AngleTBlue, BUBBLE_BLUE, 5);
AngleTBlue += rand(85,90);
Reflect(objShotBlue);
while(GetObjectDistance(objShotRed, objShotBlue) <= 10){
CreateShotA1(ObjMove_GetX(objShotRed), ObjMove_GetY(objShotRed), 1, rand(0,360), DOT_PURPLE, 5);
CreateShotA1(ObjMove_GetX(objShotBlue), ObjMove_GetY(objShotBlue), 1, rand(0,360), DOT_PURPLE, 5);
yield;
}
wait(300);
yield;
}
}
let Distance = GetObjectDistance(objShotBlue, objShotRed);
and then calling that in the while loop just makes the bubbles spew bullets 100% of the time? I mean, I can pretty easily just type out the full GetObjectDistance function, but it was just strange.
I've been trying to make a plural, so I have to make sure the singles delete themselves. That should be easy but I have little enemies objects beside the boss running around in the singles. After the single ends, the enemy keeps on moving then fires a little, and then it ends itself, kinda late. I've gotten everything else to delete itself properly except that. When the single ends, I'm not sure how to make the moving enemy object delete itself in time with the rest of the single.
Also, I just want to say these Q&A threads are really nice and helpful.
I've gone through all of Sparen's ph3 tutorials, and they are very well written (though I still don't think I can design anything :P).
That said, are there any available resources to learn about stage/package scripts?
OBJ_SPRITE_2D_LIST
in OBJ_SPRITE_2D
but I don't know how to make it stop the spellcards from starting.
Perfect. Looks like I've got it working almost the way I want it now. There's only one thing I can't seem to find a solution to. Is there a way to make the text automatically linebreak at a space?
And less important but still a little annoying, how do I make a player character not shoot during dialogue?
function ObjText_SetTextAutoLine(obj, s, len){
ObjText_SetText(obj, s);
let a = [];
ascent(i in 0..length(s)){
if(s[i] == ' '){ a = a ~ [i]; }
}
descent(i in 0..length(a)){
if(ObjText_GetTotalWidth(obj) < len){ return; }
ObjText_SetText(obj, s[0..a[i]] ~ "[r]" ~ s[a[i]..length(s)]);
}
ObjText_SetText(obj, s);
ObjText_SetMaxWidth(obj, len);
}
@Initialize{I am not sure how your Shikiekiki.png looks like, but the coordinates for SetSourceRect is 'top' , 'left', 'bottom' , 'right'.
ObjSprite2D_SetSourceRect(objBoss, 45, -50, 45, 50);
}
This is my another question (due last question came from Sparen's code), when im doing exact your tutorial, when i run ph3, they said "}" is neccesary.The second line is missing a semicolon. I think Danmakufu lets you get away with that if there's a closing bracket right after the line, so that's why it decided on that particular error message.
This is my code : // texture the boss, set centre as true centre.
ObjPrim_SetTexture(bossObj,imgBoss);
ObjSprite2D_SetSourceRect(bossObj,0,0,70,100)
ObjSprite2D_SetSourceCenter(bossObj); <--- This is the problem line
Note : The error line will be 19
I uploaded it, username is BananaCupcake.
I can't use google pics , right ?
if dist < maxspeed * weight :
speed = dist / weight
else :
speed = maxspeed
It's piecewise. ObjMove_SetDestAtWeight seems to be:Code: [Select]if dist < maxspeed * weight :
speed = dist / weight
else :
speed = maxspeed
That being said the implementation being used seems to be not super exactly accurate, but it's probably fine for most purposes.
Ok, I think the graphic must be a problem. 1. how to know its a transparent pic ? 2.Do Transparent pic affect the character appearance ?If it is a PNG file and you open it photoshop, gimp or similar programs: the background around the character should be like a checkered board. Pure black (0,0,0) is also transparent. These two things should indicate if a picture has transparency or not. Don't use paint or irfanview.
Ok, after using GIMP 2 , i saw checkered boxes (it said it was alpha channel) and i knew it was transparent, so it was the script, but why ? where did i did wrongly ? I made a pic that is the same way and it's valid but it didn't loaded it, so i knew that its the scripts fault, but where ? ??? ???
*its the same script , never changed.
How do you make spinning bullets like the ice crystals/petals in this spell? (https://youtu.be/P1wG_1w6Tcw?t=5m27s)
Hmmm hello, I'm still learning danmakufu and I'm trying to create a plural script, but apparently every tutorial I've seen is outdated and the script simply doesn't appear in danmakufu. Someone please link me an updated tutorial?
It worked, it was so legit that i forgotten the png, the pic was shikieiki.png , and i forgotten a .png because its a png file too , so. thanks for everything and apologies for my annoyancys :D :3My apologies. To be honest, I didn't understand how you fixed it. But roughly guessing it is like Sparen said with the hidden extensions. You most likely had a file being *.png.png
This question is a bit of an odd one. I want to make everything within the playing field (boss, bullets, player, background) continually spin, akin to Change Air Brave. How would I go about doing this? (yes this sounds stupid but please answer)
I've been trying to get custom sounds to play during spellcard activation and the boss's death using Helepolis's tutorials, but for some reason only the default sounds will play. I've checked the code a bunch of times - even copy&pasted the sound-related parts directly from the example file - but the result is the same every time. Danmakufu doesn't give any errors, the sounds just don't seem to be registering at all.
The .wav files are in the same folder as the script. I'm very new to this & feel like I must be missing something incredibly simple, but I have no idea what it is... :ohdear:
Could you please give an example of the code?also make sure you didnt mute danmakufu
https://pastebin.com/F7NPVQVZ This is all the code that has to do with the sounds, I think. (& I didn't mute it lol I can still hear the default stuff)
I've been trying to get custom sounds to play during spellcard activation and the boss's death using Helepolis's tutorials, but for some reason only the default sounds will play. I've checked the code a bunch of times - even copy&pasted the sound-related parts directly from the example file - but the result is the same every time. Danmakufu doesn't give any errors, the sounds just don't seem to be registering at all.
The .wav files are in the same folder as the script. I'm very new to this & feel like I must be missing something incredibly simple, but I have no idea what it is... :ohdear:
~~~
https://pastebin.com/F7NPVQVZ This is all the code that has to do with the sounds, I think. (& I didn't mute it lol I can still hear the default stuff)
Sparen finally finished the lesson!
...does that mean you'll write tutorials for stage scripts now :V
lel its another stupid question from me.
I try to fire a ring of bullets like the script here https://pastebin.com/yeQg5Dj5 , after i load it, its not defining my mainTask ! Why ? ???
Hello!
I've been using danmakufu for a while now, but I was wondering if anyone could tell me how to create a triangle or a square (or other things like that) in danmakufu. I've been trying to create shapes other than circles and diamonds, but I have no idea what to do. :ohdear:
function CreateShotShapeOA1(obj, sides, gap, speed, angle_off, graphic, delay){
let x = ObjMove_GetX(obj);
let y = ObjMove_GetY(obj);
let t = 0;
while(t < 360){
let r = cos(180/sides) / cos(((t - angle_off) % (360/sides)) - (180/sides));
CreateShotA1(x, y, r * speed, t, graphic, delay);
t += gap;
}
}
CreateShotA1(x + size*r*cos(t), y + size*r*sin(t), s, a, g, d);
Hello!Probably there is, though, why would you try to make your life more difficult?
Does anyone know how to make triangles or squares in danmakufu?
Edit:
(Oops, didn't know this was already answered. Don't mind the other message I sent).
Is there a way to do this without resorting to functions? Sure, it'll be much easier to control and such but I'm just wondering.
I know this is a stupid question , so that after i finished the script , (its the same script) however, i didn't realize that i forgotten the finalizing .I am having trouble understanding your question, but do you mean your script doesn't close? Are you using the CloseScript function to close your script? Also, forgive me for sounding rude but I would highly recommend you to follow either the video tutorials or written tutorials. These questions are really covered in those.
I tried every way to do it but it seems its not even working, So, how to do the finalize the most convenient and easiest way ? :3
Is there a way to do this without resorting to functions? Sure, it'll be much easier to control and such but I'm just wondering.wat
*The script says TEnd; its not defined.
a. I'm not sure about it, because I compared to the script that is almost the same on your tutorial 4 (I didn't put BGM's). Here https://pastebin.com/8Z1VdYhu.a. >> I doubt you're doing the same, because otherwise you wouldn't get that error. Defining tasks or functions is done using: task nameOfYourTask { } or function nameOfYourFunction{ }. You can't just call TEnd if you never defined it. That goes for any task / function or sub routine.
b.Your not rude :)
c. Its right, mine English sucks, :blush: :blush: I came from Southeast Asia so I didn't communicate with English with my family and friends .
*The script says TEnd; its not defined.
I still don't understand . its the maintask or the task TEnd ?To be honest, I have no idea what you're asking me and also I have no idea how to even explain this better than the tutorials.
What would be the ph3 equivalent of the ObjEffect_SetVertexXY function?
I'm trying to port my old danmaku script into ph3 but the wiki doesn not provide it's equivalent.
Thanks in advance
What would be the ph3 equivalent of the ObjEffect_SetVertexXY function?If I didn't misunderstood, I believe for vertex position it is ObjPrim_SetVertexPosition and for setting its textures it is ObjPrim_SetVertexUVT. You'll have to use ObjPrim_Create(OBJ_PRIMITIVE_2D); and choose a ObjPrim_SetPrimitiveType though.
I'm trying to port my old danmaku script into ph3 but the wiki doesn not provide it's equivalent.
Thanks in advance
_NextChar:すでに文字列終端です
I'm currently working on an English Patch for the fangame Touhou Riverbed Soulsaver.Memory is fuzzy, I remember running into this problem with my own game. Most likely you're breaking the commenting code such as // or /* causing the script to mess up major. Or you broke the file by saving it without Japanese font support (encoding such as SHIFT JIS or UTF-8).
I'm currently doing the Phantasm stage. After defeating the Midboss Ruri, this message appears.Code: [Select]_NextChar:すでに文字列終端です
I'm not sure what this is supposed to mean. This message appears with all three characters at the same point. The only code I have changed was the text in the dialog.
So, does anyone have an idea what causes this kind of Error?
// 次ボスロード開始
compile_file_h[1] = LoadScriptInThread(plural[1]);
LoadBossScript(compile_file_h[1]);
a question, how can I make Reimu's boundary field ?To be honest, this question is in my opinion way to generic and in the same league as: "Please make this spell card for me".
TIA
To be honest, this question is in my opinion way to generic and in the same league as: "Please make this spell card for me".
Could you be a bit more specific what exactly you want to know in order to simulate one of her spell cards?
sorry, I mean how's the mechanic works, because I'm still new to danmakufu so I want to see how the mechanic looks like
using pure black background (rgb 0,0,0) (not necessary required) and ADDITIVE rendering will make the bullets appear glowy. The way the bullet is designed also helps in enhancing this look.
Do you mind explaining which functions I should use? I don't really understand how it works.
I've run into a situation... I wanted to try and do a detailed background split up into three sections. I used 3d sprite objects split up by tiles roughly 3 to a section(so I can easily have it loop) and layers and create them all at the start, however looking at the object count and the frame that I think is caused by it in the end I feel like I feel like I'm missing something... I'm using SetCameraPerspectiveClip to try and control how many things I render but is there some way to use 2dspritelist or something to combine the all the tile sections and still display them in 3d... or is there some other trick I'm missing, any help would be much appreciated.
Hello again! So I was wondering if it was possible to implement a life extend for every 2,000,000 points. I vaguely remember seeing a post about this before but I am not sure.
It's possible. In your System script (or wherever you choose to keep track), set up a task to track score. If currscore > threshold, add extend and increase threshold by 2m.
Does the script stop crashing if you remove these? They seem pretty innocuous.
After some more testing, I managed to crash the script while the tasks were commented out. Here's the other tasks:
To confirm, Danmakufu downright CRASHES - it does not freeze/etc.
Can you pastebin the entire thing for quick reference?
https://pastebin.com/680XWj08
Danmakufu first freezes, then brings up the 'not responding' window, then closes.
Thanks for the advice. Of course, since break and return served the same purpose here the freeze still occurs.
The freeze always happens after all the bullets turn into star items, and when the player is autocollecting them.
If this is the case, you're stating that the freeze happens AFTER the attack? Are you running this as a standalone Single, as part of a Plural, or as part of a Stage?
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["test"]
@Initialize{
A;
}
task A{
loop(2){
B;
}
}
task B{
yield;
break;
}
@MainLoop{
yield;
}
@Event{
alternative(GetEventType())
case(EV_REQUEST_LIFE){
SetScriptResult(1);
}
}
Hi I'm trying to put BGM in my stage script using this function:
function StageBGM(obj, ID) {
ObjSound_SetSoundDivision(obj, SOUND_BGM);
ObjSound_SetRestartEnable(obj, true);
ObjSound_SetLoopEnable(obj, true);
ObjSound_SetLoopTime(obj, 0, 300);
if(ID == 1){ObjSound_SetLoopTime(obj, 0, 96);}
if(ID == 2){ObjSound_SetLoopTime(obj, 0, 58);}
return obj;
}
But it won't play with ObjSound_Play(bgm,1). I've checked my directory paths to my sound files. And they're all correct.
I'm not receiving any error messages.
The only way I can add BGMs right now is with #BGM and that works fine.
But I need to use this function to switch my Boss Music.
Any help out there please? ???
task TAmuletChain(dir)
{
loop(20)
{
let ex = ObjMove_GetX(objEnemy);
let ey = ObjMove_GetY(objEnemy);
let shotObj = CreateShotA1(ex, ey, 1, 270 + (85 * dir), 156, 10);
ObjMove_AddPatternA1(shotObj, 60, 2, GetAngleToPlayer(shotObj));
wait(5);
}
}
Why does this code make the amulets go out from the boss and then ... straight down?Code: [Select]task TAmuletChain(dir)
{
loop(20)
{
let ex = ObjMove_GetX(objEnemy);
let ey = ObjMove_GetY(objEnemy);
let shotObj = CreateShotA1(ex, ey, 1, 270 + (85 * dir), 156, 10);
ObjMove_AddPatternA1(shotObj, 60, 2, GetAngleToPlayer(shotObj));
wait(5);
}
}
In case you're wondering, my intention is to have them go toward the player.
So because im using a mix of tutorials so it won't might work. So instead i did only 1 point, but here's the real problem : After I created this script https://pastebin.com/TF8xTbik it says GetCenterX is not defined. ??? Why
It solved, but I can't solve this problem https://pastebin.com/0MWfFa3v (It's the same problem and it says its at the 30th line) . I think there's no problem for it but it still failed... and I'm not sure about the laser part, am i right ? or not ? ??? ??? ???
Problem number 3... Why is my bomb image not showing up? It's functioning perfectly except for that.(http://i.imgur.com/jKNajPq.png)
https://pastebin.com/S2Qi3xhh (https://pastebin.com/S2Qi3xhh)
Aaaaaand, problem number four, perhaps more significant. My bgm is skipping around right when the midboss is called and several times shortly after. I'm fairly sure the problem lies in the stage script (https://pastebin.com/6CUBCupS).Is the skipping consistent at exactly the same times? If you delay the midboss does the skipping delay in time, or does it still skip at the same points in the music? Have you tried other music to see if that also skips? It could just not like the file you're using.
So i finished the delay laser, but when i made the MainTask like this in the script https://pastebin.com/aK8Dcfq0 , the shot data is this :
ShotData{
id = 157
rect = ( 105, 431, 129, 459 )
delay_color = ( 63, 255, 255 )
It worked, but after like 10 seconds, a very big (coverment 70%) shot flew, not was i expected.
Why ?
Or my MainTask is wrong ??? ??? ??? ???
//Task for each orrery to update its position and angle
task TOrrery(let arr, let id, let offset, let color, let center) {
let orrery = CreateOrrery(color);
o[arr][id] = orrery; //add the orrery to the global array of orreries //<----- Error points here
while(true) {
let cx = ObjMove_GetX(center); let cy = ObjMove_GetY(center);
let pos = rot[arr]+offset;
ox[arr][id] = cx+r[arr]*cos(pos); oy[arr][id] = cy+r[arr]*sin(pos);
ObjMove_SetPosition(orrery, ox[arr][id], oy[arr][id]);
let angle = atan2(oy[arr][id] - cy, ox[arr][id] - cx) + angoffset;
ObjMove_SetAngle(orrery,angle+0); //point orrery at center
oa[arr][id] = angle;
yield;
}
}
This may be a dumb question, but I'm trying to find a way to prevent spawning in (0,0) when a single finishes and another one starts, my plan is to create a function in my library that ends the task where it is called. Is there any kind of command to "end" a task before it finishes?You can return from a task and that ends it just as it would a function, but you shouldn't be relying on this because you will start breaking things even more severely due to the timing-based nature of tasks, and it is harder to find those issues and solve them. Spawning at (0,0) is basically always the same easy problem where the tasks keep trying to do things at the enemy position after the enemy is deleted (or in general, anything that keeps referring to an object that's been deleted). All you have to do is properly wrap your relevant tasks in life checks or enemy deletion checks; whichever is more appropriate.
So I'm trying to use 2D arrays to hold references to several rings of "orreries" (think PC-98 Marisa) - o[0][0..4] holds the "planets", and o[1..5][0..4] hold the "moons". This is modified from a single with a single ring of orreries, with references held in 1D arrays, which works.You can't fully index into multidimensional arrays to set values, unfortunately. You can only set values of the first dimension, so e.g.
a = [[0,1,2],[3,4,5],[6,7,8]]
a[1][2] #=> 5
a[1][2] = 9 #=> error
a[1] = [3,4,9] #=> ok
temp = a[1]
temp[2] = 9
a[1] = temp
If you want to go deeper than two dimensions you then have to do this recursively.function CreateOrrery(let arr, let id, let offset, let color, let center) {
let orrery = // insert all the stuff you'd put in the original CreateOrrery function
task TOrrery(){
while(!Obj_IsDeleted(orrery)) {
let cx = ObjMove_GetX(center); let cy = ObjMove_GetY(center);
let pos = rot[arr]+offset;
ox[arr][id] = cx+r[arr]*cos(pos); oy[arr][id] = cy+r[arr]*sin(pos);
ObjMove_SetPosition(orrery, ox[arr][id], oy[arr][id]);
let angle = atan2(oy[arr][id] - cy, ox[arr][id] - cx) + angoffset;
ObjMove_SetAngle(orrery,angle+0); //point orrery at center
oa[arr][id] = angle;
yield;
}
}
TOrrery();
return orrery;
}
Right, so i was in the middle of following a tutorial to learn the basics and i was thinking i might as well test if it shows up. I save the script, launch danmakufu and... Nothing. I don't see my script, only the basic samples and EX-Rumia that come with the download. I have checked, double checked and triple checked that my header is written right and there doesen't seem to be any problem. The code obviously isn't complete yet and lacks any sort of bullets but i don't see why i shouldnt be able to even see it?#BGM header needs quotes to show it's a string #BGM["./rss_4boss"]. When a header fails the parser gives up, so nothing will show up.
I've recently finished some tutorials and decided to try some things out for myself, but, of course, I've run into a few things I don't understand and a few things that shouldn't be happening. Here's my code: https://pastebin.com/CFqhiiKt (https://pastebin.com/CFqhiiKt) At the bottom of the script is a link to some screenshots. I think the problems are from line 171 onward. What I wanted this to do was for the blue stream of bullets to circle around the boss, then, after a second, the other colors would join in. The other colored bullets, task shoot, should start firing once count reaches 60, so one second. Instead, it takes about 26 seconds for them to fire. As shown in the fourth screenshot, once the boss dies, the bullets continue to fire from the top left corner of the screen for a second before the script closes. I don't get why the blue bullets speed up after the 26 seconds, either (though that is what I wanted it to do), or why any of the bullets end up on top of each other so often. There are also some gaps in the pattern, but that might be due to a wait.First of all, the reason the bullets keep spawning in the corner is what I just mentioned to GenoCraft. The boss is dead, and soon deleted, but you haven't set it up to stop firing. If the boss dies after you call fire() but before shoot(), shoot will still run, and additionally if that instance of fire hasn't ended it will keep shooting bullets as well. So you have to be more careful with your zero-life checks.
This way you can say let bla = CreateOrrery(...) to be able to keep the object ID and the task will already be started. I'm guessing that the main reason you're saving a bunch of global arrays and using various tasks to control those arrays and cross-reference everywhere is because you didn't know you could do this.
The wiki is down. Nothing you can do about it. Try using the archived version until it's fixed: https://web.archive.org/web/20170625051804/http://dmf.shrinemaiden.org/wiki/Main_PageOh, I see, Thank you.
Right so the script is showing up in danmakufu now, thanks. However, i'm getting a strange error when i open it up. it says i need a } at line 26 but i don't see why i should.
Here's the script: https://pastebin.com/j4b6UnGh
And the error message: https://pastebin.com/CYPzceR1
I started getting error messages that I was trying to use a variable that hasn't been set yet every time anything referenced my boss object.
Now instead of manually creating a boss, I have a function in another file that checks if there's a boss stored in common data, if so returns that, and if not creates a new one, stores it in common data, and returns it.
let objBoss;
let objScene=GetEnemyBossSceneObjectID(); //For spell cards
...
@Initialize {
...
objBoss = ObjEnemy_Create(OBJ_ENEMY_BOSS);
ObjEnemy_Regist(objBoss);
ObjEnemyBossScene_StartSpell(objScene); //For spell cards
...
}
task TPluralR{
let dir = GetCurrentScriptDirectory();
let obj = ObjEnemyBossScene_Create();
//Add your singles here, e.g. ObjEnemyBossScene_Add(obj, 0, dir ~ "./S6BNS1.txt");
ObjEnemyBossScene_LoadInThread(obj);
ObjEnemyBossScene_Regist(obj);
while(!Obj_IsDeleted(obj)){
yield;
}
CloseScript(GetOwnScriptID());
}
adding more results in an error saying only "_NextChar:すでに文字列終端です"
*Spell circles not displaying properly/at all
-Task definitely being run but not getting drawn
-Static spell circles that stay there for the rest of the fight
*Game sometimes freezes (not responding) upon starting plural until I comment out all spellcards and re-add them one by one
-May simply be taking a long time to load scenes; has not yet occurred since enabling the log window
Player can bomb during Wait singles (my lazy way of adding delays between singles and spawning items)
-ForbidPlayerSpell is being set but gets ignored?
You have a lot of stuff here, and it seems you have systematic problems.
Ensure that the variable holding your boss object has been declared e.g. let objBoss;, and is in each and every single containing a boss.
You should be doing the following in each Single:
And in each Plural:
Ensure you have no weird symbols, i.e. no ????ł??? stuff in your scripts.
Depends on you you handle these. Remember that objects are not deleted at the end of a script unless you use object auto deletion or manually delete. Remember to yield; your main loop as well.
Ensure that you are calling everything in the proper block. You'll have to provide some code for this one.
Get a feel for Danmakufu's script structure and how it expects you to work with Singles, Plurals, and Stages.
task Familiar(ID, numinring, targetradius, timetotargetradius, rotation) {
let objcount = 0;
let radius = 0;
//Create the familiar
ObjMove_SetPosition(obj, ObjMove_GetX(objBoss), ObjMove_GetY(objBoss));
while (!Obj_IsDeleted(objBoss)) {
if (radius < targetradius) {radius += targetradius/timetotargetradius;}
let ang = ID * 360/numinring + objcount * rotation;
ObjMove_SetPosition(obj, ObjMove_GetX(objBoss) + radius*cos(ang), ObjMove_GetY(objBoss) + radius*sin(ang));
if (radius >= targetradius && objcount % 6 == 0) {
//Bullets.
}
objcount += 1;
yield;
}
}
-Your #Background script #Background["./system/Background_Stars.txt"] does not exist
-SetScore, etc. confuse the heck out of me. I have no idea what you're trying to do.Yeah, I have no idea how those are supposed to work either, they're from the script I started working from (Junko teaches Danmakufu). At first glance they look like they're intended to replace some of the cases in @Event, but then you look closer and it doesn't make any sense.
-You run ObjSound_Load(music,CSD ~ "./bgm.ogg") outside of a routine. Since loading the resource should be blocking, I suggest placing the loading in a routine, preferably @Loading.
-You register new boss objects twice in the same script - once in @Initialize and once in @MainLoop at frame 0. Given that you are only supposed to be able to have one in existence at any given time, this may cause problems (then again, never tested so don't know the repercussions, if there are any to begin with)That was a janky attempt to make sure it was definitely defined. The function checks if there's already a boss before making a new one, so it wasn't causing extra problems, but it didn't work so I was going to remove it later anyway.
-Your entire frame = 0 block makes no sense given that @Initialize runs immediately before the first run of @MainLoop. DRY - Don't Repeat YourselfI thought that seemed weird, but some tutorial or other had it that way and mentioned that tasks execute parallel with what called them, so I shrugged and did it that way, since I couldn't find documentation on exactly how those routines work.
-Your @MainLoop is not yielded. Literally everything in this script will crash and burn.
-In all of your attack singles, your including of Resources.txt followed by blatant DRY violation with the definition of the same functions over and over again in your MainLoops worries me. Functions are limited by scope, but if you are using the same functions over and over again, just put them in your function library once and include the library. This will make your code cleaner and easier to read.
-Your redeclaration of the global constants cx and cy as local variables everywhere in your code only impedes readability.
If you do some code cleanup, it will be MUCH easier to find the actual errors in your script.
Since the wiki is down, I suggest looking at other starter scripts (scripts where it was the second or third time someone made a proper script) - these will provide a good reference without being too bogged down in custom systems. Choose ones that are simple in scope, like some of the former contest entries that scored in the upper two-thirds.I've just been using the archived (https://web.archive.org/web/20170625051804/http://dmf.shrinemaiden.org/wiki/Main_Page) version of the wiki. I have been working off of a few such scripts, but I'll look into some more. Where would I go to find former contest entries like you mentioned?
Back here with a somewhat complicated issue I'm trying to deal with:First thing, you shouldn't model this as a nested while loop. The whole point of what you're trying to do is have [some behaviour] until a condition, then maybe some transition, then [some other behaviour]. All you need is one while loop and then the other; the way it is now isn't immediately breaking anything, but it easily could.
So, what I've been wanting to make is: spawning multiple familiars on the boss and them have them move in a circular path around her while they keep going outward and then stop at a certain distance from her. At that moment, they should start shooting bullets towards the boss.
I'm using two while-loops, one in another, with the inner one to control the familiars' movement before they reach the specified distance from the boss, and the outer (main) one to control their movement once they reached the specified distance until the script closes. Both loops are being yielded. The familiars should remain idle before reaching that distance and only start shooting once the inner loop is completed. I've inserted the task for shooting these bullets within the outer loop, so it could keep track of the exact distance between the familiars and the boss, because: once the bullets traversed that distance, they should each spawn a new bullet with the same movement angle as its parents, with the latter being deleted immediately after the spawning.
The problem I have herewith is, when the familiars reach the firstly mentioned distance from the boss, only one of the familiars starts shooting, no matter how many I spawn. On top of that, I somehow can't influence the delay between the shots. The parent bullets do spawn the child bullets at the desired location.
[...] mentioned that tasks execute parallel with what called them, so I shrugged and did it that way, since I couldn't find documentation on exactly how those routines work.Here's a post I wrote a few pages back trying to precisely (yet not formally) summarize the flow of a script:
I personally have tasks for each familiar. Each gets passed an ID (so if there are 6 familiars, the IDs are 0..5). That ID determines their angle offset.
Start with radius 0. In the main familiar loop, while radius < x, radius ++. Also give the familiar task a counter, which goes up each frame.
If radius > x && objcount % number == 0, fire bullet at boss (which will be at angle ID * 360/numinring + 180 + objcount*rotation, probably). Something like that.
EX:
...
This assumes rotating familiars. I haven't actually run it, so it might be buggy.
First thing, you shouldn't model this as a nested while loop. The whole point of what you're trying to do is have [some behaviour] until a condition, then maybe some transition, then [some other behaviour]. All you need is one while loop and then the other; the way it is now isn't immediately breaking anything, but it easily could.
The cause of the problem is likely due to the GetObjDistance and CoordToBoss functions, along with the object type RenderFamiliar returns. If GetObjDistance fails, dist is set oddly which means sdelay is also. Relatedly, if your fam objects are Render-only objects (like 2D Sprites), using functions such as ObjMove_GetX will fail, and so things in FShot that do this (such as CoordToBoss) will definitely behave wrong. Basically I wager that these sorts of things are what's screwing your idea up.
task FamiliarControl(type,angle,dir) {
let dist = 0;
let cdist = 0;
let fdist = 160;
let pdist = 0.7;
let speed = 2.5;
let sspeed = 2;
let count = 0;
let pos = [ObjMove_GetX(Boss),ObjMove_GetY(Boss)];
let fam = RenderFamiliar(Boss,type,pos[0],pos[1],120,[0,0],true,1);
while(!Obj_IsDeleted(Boss)){
if(cdist<fdist){
cdist += pdist;
}
if(cdist >= fdist && speed > 1.25 && pdist > 0.01){
speed -= 1.25/30;
pdist -= 0.69/30;
}
if(cdist >= fdist && count%16==0){
dist = GetObjDistance(fam,Boss);
FShot(fam,dir,sspeed,(dist/sspeed));
}
count++;
cdist += pdist;
angle += speed*dir;
ObjMove_SetPosition(fam,pos[0]+cdist*cos(angle),pos[1]+cdist*sin(angle));
yield;
}
}
Well, it's been working, so I'm fairly sure it exists. You might have been looking in default_system instead of system.Oh, sorry. Yeah, I looked in default_system instead.
Where would I go to find former contest entries like you mentioned?They're all on Bulletforge, for the most part. All of the "Official Thread" links on http://sparen.github.io/projects/contestdatabase.html will point to the MotK thread for each contest. All MotK contests require submitting via post in the contest thread.
Random question - where do I edit my signature on this site? "Literally everything in this script will crash and burn" seems like a very appropriate sig.It should be in Profile, at the top of each page. You MAY need a certain number of posts to unlock the feature but I do not know the specifics.
You MAY need a certain number of posts to unlock the feature but I do not know the specifics.Ah, that would be it. Looked through the rules thread and it's ten, so I'll probably hit that after the next round of crashing and burning.
Edit: Another random question, how do I get the ID of the primitive used in player scripts to draw the player? I've been playing with a card that intermittently turns everything black and white, but setting the color, blend mode, etc. of the player does nothing because that's not the object being rendered.
GetPlayerObjectID() returns the player object. Use ObjRender functions on it.That's what I've been doing, so I think it's a problem with the player script (I've been using the Mokou player from here (http://www.bulletforge.org/u/python/p/human-inferno-range-14-entry-by-python)). Tested it with some others and it works with some but not all.
I've been meaning to start using SetAutoDeleteObject, but whenever I add it the music stops playing after the first single.That shouldn't happen, as long as you're not uh handling the music inside the Single.
That shouldn't happen, as long as you're not uh handling the music inside the Single.I've been doing it in both the single and the plural, so I don't get treated to silence whenever I'm testing a new single. Is there really no way to have it both ways?
I've been doing it in both the single and the plural, so I don't get treated to silence whenever I'm testing a new single. Is there really no way to have it both ways?
This isn't quite a problem with Danmakufu itself, but rather the dmf wiki (I hope I'm posting this in the right place)
Basically I'm getting this whenever I try to go to the wiki: https://puu.sh/wE2Hs/34731e8785.png
Am I the only one getting this?
I was looking up what this php mbstring stuff was, and it all looks like server-side issues (correct me if I'm wrong). Do I just need to wait for the people who run the servers to fix the issue?
I'm fairly sure the wiki itself is down. Wait until someone fixes it, i guess :V
So I have a question in regards to loose laser hitboxes and the 'correct' way to change the direction of a loose laser.
I have observed that using ObjMove_SetAngle on a loose laser does not correctly configure the hitbox - after using the function, you can and will get hit by parts of the laser that are, well, not a part of the laser. More correctly, it would seem that the laser graphic does not match up with the hitbox.
So my question is, what is the proper way to change the angle of a loose laser in order to preserve the integrity of the hitbox as to realign with the new angle of the laser? Or is the only option to create a new laser at the point where the angle change is needed?
I don't have an answer to this, but in the same vein, how would I spin the laser but not change its movement?
Basically I'm getting this whenever I try to go to the wikiUntil it's fixed, you can use an archived version (https://web.archive.org/web/20150315061956/http://dmf.shrinemaiden.org:80/wiki/Functions_(ph3)) of the wiki.
Firstly, what kind of laser (loose, straight, curve), and secondly, what do you mean by 'not change its movement'? Do you mean static base straight lasers rotating around their base?
So I have a question in regards to loose laser hitboxes and the 'correct' way to change the direction of a loose laser.Do you have a minimal working example? I'm not really sure what the problem is since I've never really run into this.
I have observed that using ObjMove_SetAngle on a loose laser does not correctly configure the hitbox - after using the function, you can and will get hit by parts of the laser that are, well, not a part of the laser. More correctly, it would seem that the laser graphic does not match up with the hitbox.
So my question is, what is the proper way to change the angle of a loose laser in order to preserve the integrity of the hitbox as to realign with the new angle of the laser? Or is the only option to create a new laser at the point where the angle change is needed?
My my.... this is very anooying......You need to use ObjMove_SetAngularVelocity(obj, agv) on the curvy laser object, otherwise it will just behave like an ordinary loose laser.
I am creating some curve lasers in this script : https://pastebin.com/HMqXPpbr
So i'm using this shot sheet : Expanded shotdata ZUN style PH3, by Ozzy (ZUN original sprites)
but it didn't even looked like a curvy laser ! It's only straight ones, looked like half transparent.
But if i used all the README said the directory of #include, the script will won't appear.
I can't use the curvy laser :( :( any help ? :)
My my.... this is very anooying......
I am creating some curve lasers in this script : https://pastebin.com/HMqXPpbr
So i'm using this shot sheet : Expanded shotdata ZUN style PH3, by Ozzy (ZUN original sprites)
but it didn't even looked like a curvy laser ! It's only straight ones, looked like half transparent.
But if i used all the README said the directory of #include, the script will won't appear.
I can't use the curvy laser :( :( any help ? :)
I'm making a loose laser that acts like Sese's bones in Lenen: they spin about their center, but their movement isn't dependent on the 'angle' of the laser.One possibility might be to define it in your shotsheet. For example, Marisa's stars spin like you described. Their definition looks like this:
ShotData{ id=661 rect=(240,153,255,168) render=ADD_ARGB fixed_angle=false angular_velocity = 2 delay_color= (255,255,255) }
The relevant bits being the "fixed_angle=false" and "angular_velocity = 2".
Do you have a minimal working example? I'm not really sure what the problem is since I've never really run into this.
Also for the half-transparency you can solve it by setting ObjCrLaser_SetTipDecrement(laser,0.1).
In future, maybe refer to Sparen's tutorials and the danmakufu wiki before asking here.
I ended up just creating new lasers. I was having loose lasers bounce off of the edges - I am under the assumption that upon direction change, the alignment of the hitbox remained the same (IE the vector representing the hitbox did not rotate, only the graphic), or that there was some other issue when they bounced off the sides. The workaround I used seems to look fine.That's sort of why I'm confused because that shouldn't happen unless maybe you accidentally use ObjRender_SetAngle instead. If you have a solution then whatever though.
How to disable the number show up when player collect item ?Use ObjItem_SetRenderScoreEnable(item,bool) and put false as the second parameter.
How do i aim a straight laser to a certain object?To aim it at a desired object, you need to calculate the angle from the straight laser source to the object using atan2.
let laserAngle = atan2(y1-y2,x1-x2);
So I am wondering.... that how to make bullets act/shoot like Hina's last spell (Pain Flow) and bullets curves like gengetsu's last attack ?
*its not gengetsu rape time
Soon after i edited, it said angleToPlayer is not defined, I'm not so sure about where to make it defined, any ideas ? https://pastebin.com/qNb1FTtsYep, angleToPlayer is a custom function that I took from Helepolis' tutorials quite a time ago and pretty much kept it unaltered. I wrote it in one of the #include files of the script I took the task from.
*if you don't mind, send the full script and i'l try to observe :3
What part of it? The blending or the motion? If it's the latter, it works the same as Junko's, for which I have a writeup here:It's the latter, thank you!
https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1257975.html#msg1257975
And, .... how to replicate Mishaguji-sama ? :3
When i change intersection circle of a shot via ObjShot_SetIntersectionCircleA1 it doesnt intersect with any other objects, making IsIntersected_Obj_Obj impossible to use, while if i dont change the intersection circle, it works fine. Is there any other way to register the intersection of 2 objects except for IsIntersected_Obj_Obj?
ObjShot_SetIntersectionCircleA1
Parameters:
1) object ID (real)
2) hitbox radius (real)
Creates a hitbox of specified radius for collision detection of the shot object. In order to maintain the hitbox, it must be set every frame. There can be multiple hitboxes set for one shot object.
In other words, set the hitbox every frame and it should work as intended.
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){
let angleT = GetAngleToPlayer(objBoss);
loop(13){
ascent(i in 0..1){
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2.5 - i/3, angleT, 406, 5);
}
ObjMove_SetAngularVelocity(obj, -10) ;
angleT += 360/12;
}
wait(50);
}
any ideas ? it doesn't spin like it... ???
https://pastebin.com/eLFp9uZ0
can obj be 0 ?
How can I get and object's alpha? I can't find a function that does that.Unfortunately, there is no function for that. If you want to track an objects alpha, you can try to use Get/Set Values (https://dmf.shrinemaiden.org/wiki/Object_Functions#Obj_SetValue) and pass the alpha value through. That way you can some sort of track an object's alpha.
function someObject() {
let obj = ...
let alpha = 200;
Obj_SetValue(obj, "alphaValue", alpha);
return obj;
}
task testRetrieveAlpha() {
let testObject = someObject();
let retrievedValue = Obj_GetValue(testObject, "alphaValue");
<generic text object prints 'retrievedValue'>
}
If the text object is produced, it should report 200. Above can be turned into more "object orientated" methods/functions, but I tried to keep it simple here.
After i let "let obj = CreateShotA1;", then it says that it's not the correct parameters , any ideas ? .-.
Hey guys! I am new in the scripting world, just began this week and I have some problems with a pattern :(. I fact, I don't understand why it does something like that :ohdear:, I need someone to try it and tell me why it does something like that, and how you would fix it :blush::
https://drive.google.com/drive/folders/0Bwf7GLCc6Z9JbWh3NjF3YTlfdW8?usp=sharing
As you can see, the problem resides in the delay laser. I want my big stars to explode only when hitting the delay laser, but when the laser hits the bottom of the screen and teleport to the top, everything explode, I really don't get it ???.
I think it's because of the fact that the laser doesn't actually warp to the top, but goes really fast to the top while hitting the stars, which cause the stars to explode, but why? I've set the laser to teleport to the top, it shouldn't do something like that... :ohdear:
Actually, I was able to fix it, but in a weird way that I don't understand, so I still need someone to tell me how he/she would do :D.
Greetings fellow scripters and aspiring scripters! I'm KIND of new to Danmakufu and I'm using Sparen's Danmakufu Tutorial website in order to learn Ph3. However, I'm stuck in this one question and no matter how much I read Part 3 of Lesson 5, it doesn't seem to get into my head. Now I love answering the questions with a little explanation so I can put it in my notes for future reference, but I'm not able to do that since I can't make heads or tails of this question.
Image link to the question: https://ibb.co/gi6R4k
Now it tells me that the answer is B. Now do any one of you know why? I would really appreciate a nice juicy answer from you guys and I thought it would be best to ask this question in the Danmakufu Q&A~
Greetings fellow scripters and aspiring scripters! I'm KIND of new to Danmakufu and I'm using Sparen's Danmakufu Tutorial website in order to learn Ph3. However, I'm stuck in this one question and no matter how much I read Part 3 of Lesson 5, it doesn't seem to get into my head. Now I love answering the questions with a little explanation so I can put it in my notes for future reference, but I'm not able to do that since I can't make heads or tails of this question.
Now it tells me that the answer is B. Now do any one of you know why? I would really appreciate a nice juicy answer from you guys and I thought it would be best to ask this question in the Danmakufu Q&A~The minimum value you give ascent/descent is inclusive, while the maximum value is exclusive. The first time the loop runs i = 6, and the last time has i = 22.
I'm wondering if there's a ph3 thread for useful code snippets, and/or a library of extra functions to make life easier?Not exactly. There are a lot more people scripting now and there are a lot of people rolling their own various systems. At this point you just kind of have to communicate with people and find scripts with useful snippets or bigger libraries that allow reuse.
stuffRight off the bat: Please, please write and test your code in smaller chunks. Part of why it's difficult to respond to this is because there isn't just one problem to point at; you've written a lot at once and now instead of a simple answer there are a bunch of things to look at.
Well, I guess no one's going to help me like that so let's be more specific: When I fix this problem, I have some random stars popping out from the top left corner of my screen. I tried all sort of things like cancel the function that make my stars explode when the laser teleport to the top, or deleting all explosion outside from the screen thinking that the small stars were stacking outside from the screen and reappearing at the top left corner, and trying out other things. The conclusion to this would be that all the stars that explode from hitting the delay laser stack for reappearing later, but I didn't ask for this, I don't get it, can someone help me?
This is a recurrent problem since in my other scripts, I have the same problem with random stuff popping out from the top left corner of my screen. I thought it was because danmakufu could't interpret functions outside from the screen so to fix that it would make them happen at X=0 and Y=0 but now I am lost.
task starBullet(x,y,velocity,angle,bulletType,delay) {
let obj = ...
while(!Obj_IsDeleted) {
if(I interact with the laser complicated statement code) {
explosion(obj);
Obj_Delete(obj); // <-- if explosion is a task and not a tunction then 0,0 spawning issue might occur.
}
}
}
function explosion(obj) {
// do whatever new explosion stars you want to create here using CreateShotA1
}
< snip >
< snip >
let b = CreateStraightLaserA1(200, 100, 90, 512, 2, 0, SHOT_RING_RED, 10000);
orlet b = CreateStraightLaserA1(200, 100, 90, 512, 2, 10000, SHOT_RING_RED, 0);
ObjShot_SetIntersectionEnable(b, false);
And maybe making it resistant to bullet cancels or something if you need to.
stuff
The only explanation I see to this is because this never happens as the stars can't detect 1pixel of heightWell, basically. That will only work if the two numbers are actually equal, which is probably not going to ever happen when you're using random angles and velocities that will cause the bullet's y-position to rarely be exact integers. In general you shouldn't be looking for exact equality with something like this because of how unpredictable the numbers are.
while(ObjMove_GetY(obj2) < x){yield;}
while(ObjMove_GetY(obj2) > x){yield;}
it would work as intended. If you look at the picture I posted and work out what would happen when the conditions are swapped, you would find that for the same reason the current way fails (the second condition only checks once you finish the first one), this way would succeed.if( (|ObjMove_GetY(obj2) - x|) < 4){ explode(); }
Where 4 here is just the range, and the (| |) are for taking the absolute value. For example, if the bullet's y-position is 200, and x is 198, then |200 - 198| = 2, which is less than 4. And if x were 203, then |200 - 203| = 3. So this way would also work fine.
stuffOh my god, I completely forgot that danmakufu doesn't only read integer numbers but can also read infinitesimal numbers, so indeed, the odds to have the same numbers is null. And for if( (|ObjMove_GetY(obj2) - x|) < 4){ explode(); }, I would never have thought of this, it's quite clever. For the "while" solution, I feel dumb too x)
Variables of different types are being compared
(型が違う値同士を比較しようとしました)
I:/th_dnh_ph3/script/test MC/test.txt
test.txt line(行)=74
↓
if(type==true){
Need help here!What is exactly your question?
(http://i.imgur.com/AyEdFsP.png)
As I have seen on Nezu Akitsu's |Hoshikami (Star Fox) "Akitsu Nebula"| from Tri Focuser, I might have a grasp difficulty while I'm thinking of creating a shaped laser in a radius like the one with a triangle picture spinning.
Anyone who have knowledge to do about spinning shape lasers? Please Respond!
I've been waiting till December for one of my first complete scripts to be done! :ohdear: :ohdear:
I think he wants to know how to make a spinning shape made of lasers.I am aware what the user wishes/desires, but no specific question was stated. It doesn't really helps to increase font size, change colours and bold out things. Mark up is useful when used proper. Not like this.
HumanReploidJP you're not a native speaker, are you?
WriteLog((16.1 - 16) == 0.1);
it return false
while WriteLog(ator(16.1 - 16) == 0.1);
return true
Anyone know why?2. I like scripting but i really suck at cut-in's, so if you all dont mind help me as well thanks so much :3 https://pastebin.com/BNQEF2VAYou have the wrong number of arguments for the cutin function. It requires (type,spellcardname,cutinImg,left,top,right,bottom). You're missing the spell card name. I imagine that the error has resulted from argument 3, cutinImg, being a number instead of a file path string like it's supposed to be. Danmakufu's error messages are not always very good at pinpointing the precise location of the error.
and i run the script this happened :ohdear: :ohdear: (sorry for interruption but i suck doing these..)
Variables of different types are being compared
(型が違う値同士を比較しようとしました)
I:/th_dnh_ph3/script/function_cutin.txt
function_cutin.txt line(行)=67
↓
if(type == 0) { x = GetClipMaxX; y = GetCenterY+10; }
if(type == 1) { x = GetClipMaxX+256; y = GetCenterY-120; }
if(type == 2) { x = GetClipMinX-256; y = GetCenterY; }
// handlers
summontext;
summonhexagon;
cutinEffect_Alphret(obj,as,alphre
~~~
Hi againJust tested your code out and it works actually perfectly fine. Perhaps the graphic you're using isn't precisely centered, causing the circle to behave strangely (as you've described).from my very stupid questions,
1. So I made a magic circle but I think it was unstable and it moves not in the center but pushing left and right ...
it looks weird so I ask it, this is the code:
task magiccircle(objBoss,size,type){
let obj=ObjPrim_Create(OBJ_SPRITE_2D);
let GCSD = GetCurrentScriptDirectory;
let img=GCSD~"MG (2).png";
let spin = 0;
let s = 0;
LoadTexture(img);
ObjPrim_SetTexture(obj,img);
ObjSprite2D_SetSourceRect(obj,0,0,256,256);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetScaleXYZ(obj,size,size,size);
ObjRender_SetAlpha(obj,230);
Obj_SetRenderPriority(obj,0.35);
while(!Obj_IsDeleted(objBoss)){
spin += 3;
ObjRender_SetAngleXYZ(obj,0,0,-spin*1.5);
ObjRender_SetPosition(obj,ObjMove_GetX(objBoss),ObjMove_GetY(objBoss),0);
if(type==true){
ObjRender_SetScaleXYZ(obj,size+0.2*sin(spin),size+0.2*sin(spin),0);
}
ObjMove_SetPosition(obj,ObjMove_GetX(objBoss), ObjMove_GetY(objBoss));
yield;
}
Obj_Delete(obj);
}
I found out the cut function worked out just fine, but its only without Backgrounds https://pastebin.com/rEHEszEK
with the backgrounds the cut in is failed to show, what is happening to the BG ?
The assigned rects are SCREEN_WIDTH and SCREEN_HEIGHT, or 640 and 480 respectively (depending on what was set in your def file, if you use one).I have the following in my th_dnf.def:
screen.width = 1024
screen.height = 768
But SCREEN_WIDTH/SCREEN_HEIGHT seem to provide old values (640 and 480, respectively) nonetheless. Why do they behave like that? Or should I write something else in .def file in order to get new values from these constants? Haven't seen anything related in this thread and wiki.
speed = ( x_speed^2 + y_speed^2 )^0.5
angle = atan( y_speed / x_speed )
There is an AddPatternB series just like AddPatternA.Oh, I see. Sometimes I kinda forget AddPattern exists :V
https://dmf.shrinemaiden.org/wiki/Move_Object_Functions#ObjMove_AddPatternB1
That being said, there is no such thing as directly setting "x-speed" and "y-speed" as you would with ObjMove_SetSpeed and SetAngle because CreateShotB and AddPatternB probably just convert into speed and angle anyways. If needed you can calculate this yourself withCode: [Select]speed = ( x_speed^2 + y_speed^2 )^0.5
angle = atan( y_speed / x_speed )
let x = ObjMove_GetX(laser);
let y = ObjMove_GetY(laser);
let a = ObjStLaser_GetAngle(laser);
let len = ObjLaser_GetLength(laser);
let num = 8;
ascent(i in 0..num){
let dist = i*len/num;
let shot = bullet(x + cos(a)*dist, y + sin(a)*dist); // make a bullet, this is just the xy position
movebullet(shot);
}
task movebullet(shot){
// do whatever bullet movement
}
let shot = bullet(x+cos(a)*(i*len/num), y+sin(a)*(i*len/num)); // this is just the xy positionSorry I am dumb, May i know what and how is the "bullet" functioned ? I can't make it defined or getting it right
Hello!
I have another problem. I was following Sparen's tutorial for making snaking lasers, but the bullets don't appear at all. I'm not sure what to do.
Here is the script:
task MainTaskA{
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){
let wait = 180;
loop(wait){yield;}
fireA;
}
task fireA{
let px = GetPlayerX();
let py = GetPlayerY();
let angleT = 0;
ascent(i in 0..12){
let obj = CreateCurveLaserA1(bossX, bossY, 4, GetAngleToPlayer(objBoss) + i*360/12, 60, 18, C_LASER_RED, 10);
SnakePattern(obj, 1);
}
}
task SnakePattern(obj, dir){
let wvel = 1*dir;
ascent(i in 0..12){
ObjMove_AddPatternA2(obj, i*30, NO_CHANGE, NO_CHANGE, NO_CHANGE, wvel, NO_CHANGE);
wvel *= -1;
}
}
}
let shot = bullet(x + cos(a)*dist, y + sin(a)*dist); // this is just the xy position
Now good, I wish i could solve this complicated question because I'm simplytoo young to understand
let shot = bullet(x + cos(a)*dist, y + sin(a)*dist);
withlet shot = CreateShotA1(x + cos(a)*dist, y + sin(a)*dist, 2, 90, 45, 10);
Just to show what it should be doing. This should spawn individual bullets that just move down, but because they're in that ascent loop there will be eight of them at once.Eee, im so new to this scripting stuff can someone tell me, how to make two bosses with hitboxes and its own hp? like yatsuhashi and benben or satono and mai fight? Im using aldryn system btwMaking two bosses is done spawning the second boss as a regular enemy. Enemies logically have their own hitbox and life before they "die". See the wiki for the required functions to define these.
Im using aldryn system btw
Making two bosses is done spawning the second boss as a regular enemy. Enemies logically have their own hitbox and life before they "die". See the wiki for the required functions to define these.
I have no idea what an aldryn system is. Google isn't helping me either.
Since you're new to this stuff. What kind of experience do you even have when it comes to Danmakufu?
im suddenly addicted with bullet patterns tho, so i only focused in composing such patterns by myself, and im learning from some presets like spell card collectionI was actually wondering about your technical knowledge, such as objects, primitives, sprites, methods and so on. Have you ever created 2D and 3D sprite effects?
I was actually wondering about your technical knowledge, such as objects, primitives, sprites, methods and so on. Have you ever created 2D and 3D sprite effects?Mmmno, im using some completed single script and just change the sprite using gizmo's sprite library, i never create such render object before
Mmmno, im using some completed single script and just change the sprite using gizmo's sprite library, i never create such render object beforeI was afraid of that. Nothing personal, however, explaining things now isn't going to help you. I am not going to program it for you. If somebody else already has such a feature and allowing it to be used then that would be easiest for you. I don't have circular life bars in my own game so my help ends here.
I was afraid of that. Nothing personal, however, explaining things now isn't going to help you. I am not going to program it for you. If somebody else already has such a feature and allowing it to be used then that would be easiest for you. I don't have circular life bars in my own game so my help ends here.
Oh, My bad
Also, How to make a Ring of bullet that will drops down like CreateShotB2?
if you meant it acted like it has gravity then try using ObjMove_AddPatternB2
yeah but in a default or simple ring before the bullets separated away
Hello!The wiki won't necessarily have that information because there's no set framework for it. You draw the portraits and boxes and text and everything and that's just how it works. Typically you might set this up inside of a single script that you add to the boss plural as though it were an attack.
It's Dire again here. The wiki doesn't really have any tips on making a dialogue scene, so how do I do that? How does one go about making a dialogue scene in danmakufu?
Thanks!
Here's a curious question; has MKM fixed the alpha rendering in PH3 so that objects with less transparency in alpha rendering no longer get darker? Internally, in v1.2m, using ObjEffect_SetVertexcolor(obj, idx, rgba) multiplied the rgb by a factor of a. So in the shader, so we'd get something like: color.rgba = (color.a * color.rgb, color.a) // internally, rgba are values of 0-1.Note that this isn't strictly a mistake. What people expect when declaring alpha values is straight alpha blending, where rgb and alpha are uncorrelated, but vertex color filtering expects premultiplied alpha in order to compose it with other layers. It was a problem because you couldn't get around it just in scripts, whereas any modern API will be doing this for you when you supply the color values.
Also, what about the pixel-perfect issue? PLEASE tell me that was fixed too.Yes, but I'm not sure to what extent you're looking for. Much of the interpolation issue for bullets is due to being rotated at arbitrary angles; this can be disabled by setting fixed_angle=true in your shot definition. I specifically asked for this to be implemented in order to fix this issue and it definitely helps.
I.e. I want some of my bullets look like this:
(https://image.ibb.co/ngxv4Q/pixel_perfect.png)
And not have the the artifacts like I had in the past when rendering similar bullets:
(https://image.ibb.co/coa4yk/non_pixelperfect.png)
It was a problem because you couldn't get around it just in scripts, whereas any modern API will be doing this for you when you supply the color values.Oh thank goodness! This is great news for me.
But yes you can just set alpha values independently now and it's fine.
Yes, but I'm not sure to what extent you're looking for. Much of the interpolation issue for bullets is due to being rotated at arbitrary angles; this can be disabled by setting fixed_angle=true in your shot definition. I specifically asked for this to be implemented in order to fix this issue and it definitely helps.Oh wow, thanks for making that suggestion. I remember reaching out to MKM myself... helpful guy, he was nice enough to share the source of of the script-engine in DNH with me (I still have it, if anyone wants... it's good study material for how lexer/parsers work as well as Bytecode and FSMs). But also, that's not the only thing. To have perfect pixel texture mapping, you'd need to map texels to pixels (https://msdn.microsoft.com/en-us/library/windows/desktop/bb219690(v=vs.85).aspx) perfectly. Disabling bullets from rotating about arbitrary angles solves a part of it; the other part involves mapping bullets in such a way that the coordinates map to integer values. I believe in D3DX10+ it's done a little more intuitively (https://msdn.microsoft.com/en-us/library/cc308049(v=vs.85).aspx). In script, this just means changing our code to floor the coord-value, but this is computationally expensive to do in a script environment. Perhaps we could make this suggestion as well? I can see how it can help with the rendering of certain sprites and especially bullets.
However, there is also interpolation introduced from sprites not being drawn at exact integer bounds ("bounds" because sprites with an odd-sized width/height would have to be drawn at half-pixel positions).
the other part involves mapping bullets in such a way that the coordinates map to integer values. I believe in D3DX10+ it's done a little more intuitively (https://msdn.microsoft.com/en-us/library/cc308049(v=vs.85).aspx). In script, this just means changing our code to floor the coord-value, but this is computationally expensive to do in a script environment. Perhaps we could make this suggestion as well? I can see how it can help with the rendering of certain sprites and especially bullets.I already knew this was the case when I made the request back then, but despite implementing the fixed angle parameter, he probably didn't realize this wouldn't fix the issue entirely. I didn't want to press the issue when he had just done the work. At this point development has been halted for a while now though; mkm has a family and full-time job and whatnot so we might not see any future updates unless he decides to release the source or have someone take over.
Also, good to see you still active, Drake. I wonder if Naut and Nuclear Cheese is still around too?nah lol
is there a way to restrict player movement so that the player cant move for a period of time
#UserItemData
item_image = "../img/item.png"
ItemData{
id = 1
type = 2
rect = ( 0, 0, 12, 12 )
render = ALPHA
}
ItemData{
id = 2
type = 2
rect = ( 14, 0, 26, 12 )
render = ALPHA
}
ItemData{
id = 3
type = 3
rect = ( 26, 0, 40, 12 )
render = ALPHA
}
let HEALTH = 1;
let SPELL = 2;
let POINT = 3;
@Initialize{
let path = GetCurrentScriptDirectory ~ "./item_data.dnh";
LoadItemData(path);
SetDefaultBonusItemEnable(false);
}
@MainLoop{
yield;
}
@Event{
alternative(GetEventType)
case(EV_GET_ITEM){
let itemtype = GetEventArgument(0);
if(itemtype == 1){
if(GetPlayerLife < 250){ SetPlayerLife(GetPlayerLife+1); }
}
if(itemtype == 2){
if(GetPlayerSpell <= 1295){ SetPlayerSpell(GetPlayerSpell+500); }
}
}
}
2. How can the shot at TShot01 to TShot08 acts exactly like TShot11 to TShot18 , but spins at the opposite direction ?
I tried a few ways but I stops at a direction at the end, so....
https://pastebin.com/H8xEz1yj
Okay, I'm having a really dumb and confusing problem here.One quirk that is probably the cause of the graphics screwup is that you seemingly cannot start the item_image path with ../. If you use "./../img/item.png" it might work.
My items work as intended, but their graphics aren't showing up. I have double-checked, and both the directory paths and graphic rects are 100% correct:
1. After I called this, the sound "capture" is weirdly cut a lot so I can barely hear very little sound length... (the sound was present)
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
if(ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SHOOTDOWN_COUNT)
+ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SPELL_COUNT) == 0){
AddScore(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE));
PlaySound("capture",100,0);
} else {PlaySound("failed",100,0);}
Obj_Delete(objBoss);
DeleteShotAll(TYPE_ALL,TYPE_IMMEDIATE);
SetAutoDeleteObject(true);
CloseScript(GetOwnScriptID());
return;
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
if(ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SHOOTDOWN_COUNT)
+ObjEnemyBossScene_GetInfo(objScene, INFO_PLAYER_SPELL_COUNT) == 0){
AddScore(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE));
PlaySound("capture",100,0);
} else {PlaySound("failed",100,0);}
Obj_Delete(objBoss);
DeleteShotAll(TYPE_ALL,TYPE_IMMEDIATE);
SetAutoDeleteObject(true);
loop(120) { //delays the script closure by 120 frames (120 is an exemplary value here, use one that suits your needs)
yield; //or if you have a 'wait'-function, use it here
}
CloseScript(GetOwnScriptID());
return;
Good time of day,Contact KimoKeine (aka Blargel, administrator of Bulletforge) at channel #danmakufu on IRC. He can help your friend to get an account.
I have a question that is not really relevant to danmakufu. I want to ask about bulletforge. I have one friend, who is already writing on a danmakufu and would really like to upload his projects on that site, but he can't, since bulletforge isn't currently open for registrations. However, I had heard that people, kind of, can write an email to somebody and thus register there... Is that so? Or is there any other solutions?
Thanks in advise!
I'm trying to use gtbot's cutin function in a script but the spellcard name doesn't disappear in the end for some reason. It was supposed to disappear when the boss is deleted, so I tried to set the boss the same way as the sample script(let objBoss= GetEnemyBossObjectID[0];) but it returns this error: Array index out of bounds. What am I doing wrong?
Needed to ask that currently I am frustrated at this problem :)
How to let bullets reflects at all sides ? https://pastebin.com/DdjzZqB0
The library assumes you have Object Autodelete turned on.Oh, so that's why it worked in another script. But how can I play the music with Object Autodelete on if it stops after every single?
SetAutoDeleteObject(true);
missing the conditionDoes the condition same as the GetStgFrameWidth... to >0 ? If not what is the condition (I do suck at advance math) ? I can't try it now because I'm going to be busy through all weekdays...
Oh, so that's why it worked in another script. But how can I play the music with Object Autodelete on if it stops after every single?
Does the condition same as the GetStgFrameWidth... to >0 ? If not what is the condition (I do suck at advance math) ? I can't try it now because I'm going to be busy through all weekdays...To be more specific:
The fact that you're replaying music tracks at the start of every single worries me. I suggest loading and playing music tracks in either a Stage or Plural, whichever you use.Oh, I see. I'm new to plural scripts so there's a lot I don't know yet... It worked, thanks!
In general, if a task must run for the duration of a boss fight, don't run an abbreviated version at the start of every single if it's going to have a significant effect on the player's experience.
task renderPlayer // Render Player
{
ObjPrim_SetTexture(playerObj,playerTex); // Set Texture
Obj_SetRenderPriority(playerObj,31); // Set Render Layer
ObjRender_SetBlendType(playerObj,BLEND_ALPHA); // Set To Alpha
ObjRender_SetAngleXYZ(playerObj,0,0,0); // Set Rot
ObjRender_SetScaleXYZ(playerObj,1,1,0); // Set Scale
ObjRender_SetAlpha(playerObj,255); // Set Alpha
ObjSprite2D_SetSourceRect(playerObj,0,0,32,54); // Set Rect
ObjSprite2D_SetDestCenter(playerObj); // Set Center
ObjRender_SetPosition(playerObj,GetPlayerX(),GetPlayerY(),0); // Set Player Position
while(!Obj_IsDeleted(playerObj))
{
ObjRender_SetPosition(playerObj,GetPlayerX(),GetPlayerY(),0); // Set Player Position
renderHitbox(GetPlayerX(),GetPlayerY());
if(GetKey(VK_LEFT)) // Going Left
{
ObjRender_SetAngleY(playerObj,0);
}
else if(GetKey(VK_RIGHT)) // Going Right
{
ObjRender_SetAngleY(playerObj,180);
}
else
{
}
yield;
}
}
The code is called on Initialize. I would like some help. Thanks
Hi from me again.
https://pastebin.com/qAzMJg27
The code up there summons two bosses.One of them acts fine, but the another one cannot shoot nor move, i tasked them quite correctly. What should I needed to do ?
If i spawn a straight laser from a random position and angle, how do I calculate the spot where it enters in contact with the walls or top of the screen?
https://en.wikipedia.org/wiki/Line?line_intersection (https://en.wikipedia.org/wiki/Line?line_intersection)After reading through that page, I realized I can't undertand anything... Probably because my main language isn't english so I don't understand many of the terms used there as I likely already learned them in another language...
You know the two points that mark the start and end of your laser, and you have the four corners of the screen, so using the equations using the formulas of the two lines should be fine.
function GetSTGFrameIntersectPoint(x, y, t){
let wall = [[384,448], [0,448], [0,0], [384,0]][floor(t/90)];
let h = min( (|(wall[0]-x) / cos(t)|), (|(wall[1]-y) / sin(t)|) );
return [x + h*cos(t), y + h*sin(t)];
}
There's also this fun solution I worked out that is more specific than the line-line, taking note that you'll always make right triangles with the walls.Thank you, that works just fine!Code: [Select]function GetSTGFrameIntersectPoint(x, y, t){
let wall = [[384,448], [0,448], [0,0], [384,0]][floor(t/90)];
let h = min( (|(wall[0]-x) / cos(t)|), (|(wall[1]-y) / sin(t)|) );
return [x + h*cos(t), y + h*sin(t)];
}
This probably works. Minimums with infinity should play nicely. I don't really want to explain the math and logic behind what exactly I'm doing here lol.
Immediate first question is, do you have a yield in your MainLoop. If not the task will yield once but never be yielded back to, so nothing will keep running.Ahh. It turns out I didn't even have the main loop at all, I didn't know It was so essential. Thanks!
Task scheduling and yielding work by having the program execute a script until it hits a yield, at which point it stops where it is and "puts it aside" in a queue for later. In most cases, you'll start a bunch of tasks from @Initialize, which only runs once, so the tasks started there will run a bit, yield (or end), and eventually @Initialize finishes. After this the @MainLoop runs once per frame, even if it's empty or you didn't write anything. If you leave it like this without a yield in it, there's nothing to tell the script engine to go back to those other tasks. If you put a yield in, then the MainLoop will hit it, the script engine goes "ok I'll save the MainLoop for later" and puts it at the back of the task queue, picks up at the start of the queue, and goes through all the tasks until it reaches the MainLoop again, which might have some more code, finishes, and the script waits for the next frame for it to run again.Interesting. But I don't want to clog the thread with our conversation. It's the garage, not the recovery centre. But thanks for sharing!
To explore this, you can try putting two yields in the MainLoop, and all the tasks will run "twice as fast", because the task scheduler will go through the whole queue twice before the MainLoop ends.
I have two problems.
1) I get this error saying: EnemyBossSceneが作成されていません. I have no idea what it means but it probably due to my lack of knowledge on how to make a boss script. script: https://pastebin.com/4VP6srRa
You only need a scene object in single scripts. Your script is a plural. You are also creating a boss object, which makes no sense given that the plural is a container that creates the 'boss battle' itself.
Please refer to: https://sparen.github.io/ph3tutorials/ph3u2l12.html
More specifically, you're using GetEnemyBossSceneObjectID to try and get the boss scene, which isn't created yet (you create it in TPlural). Then you try to StartSpell it when it isn't set up so it errors, but as Sparen says it isn't what you'd be doing in the plural anyways. Get rid of those calls, you don't need or want them. You also don't call TPlural anywhere so that never runs.
As for the second, I dunno why you set up an extra Sprite object to draw the player sprite when Player objects already are one. But your actual problem is just that you use Obj_SetRenderPriority which ranges from 0 to 1 instead of Obj_SetRenderPriorityI which ranges from 0 to 100, so 50 and 31 just max out to 1 and the sprites are drawn above the frame, which makes the origin the top-left of the screen instead of the play area.
Drake) 2) Ah thanks so much. It worked.
Drake & Sparen) 1) Ah It does work... but what do I do for a boss to appear like making a boss in a single script. Do I just make a boss for all the single scripts?
In every single script that is part of a boss scene, create a new boss object. For more information, please read the tutorials.Thanks!
The fact that you're replaying music tracks at the start of every single worries me. I suggest loading and playing music tracks in either a Stage or Plural, whichever you use.Still on this, how do I change the music mid-battle? I want a certain song to play for the first 3 singles and then change to another one.
In general, if a task must run for the duration of a boss fight, don't run an abbreviated version at the start of every single if it's going to have a significant effect on the player's experience.
Still on this, how do I change the music mid-battle? I want a certain song to play for the first 3 singles and then change to another one.
//So I have this problem with GetShotIdInCircleA1 where it's not getting anything!
//wait(60); Commented this out just to test quickly
let bullets = GetShotIdInCircleA1(x,y,99999); // This Should Get every Bullet. I Just set it to 99999 to test it.
ascent(i in 0..length(bullets)) // Foreach bullet in bullets...
{
ObjMove_SetAngle(bullets[i], GetAngleToPlayer(bullets[i])); // Set Bullet Angle to Player
Obj_Delete(bullets[i]); // Here for debugging purposes
}
Obj_Delete(bullets[0]); // I tried this to try to find why the code dosen't work and It's apparently because the array index is out of range.
// Thanks!
Code: [Select]//So I have this problem with GetShotIdInCircleA1 where it's not getting anything!
//wait(60); Commented this out just to test quickly
let bullets = GetShotIdInCircleA1(x,y,99999); // This Should Get every Bullet. I Just set it to 99999 to test it.
ascent(i in 0..length(bullets)) // Foreach bullet in bullets...
{
ObjMove_SetAngle(bullets[i], GetAngleToPlayer(bullets[i])); // Set Bullet Angle to Player
Obj_Delete(bullets[i]); // Here for debugging purposes
}
Obj_Delete(bullets[0]); // I tried this to try to find why the code dosen't work and It's apparently because the array index is out of range.
// Thanks!
1. What are you trying to doSorry if the post wasn't clear, I was experimenting with my post.
2. If run before there are any bullets spawned, it will always fail because bullets[] will be empty - that is likely the cause of your problem
task fire02
{
while(true)
{
let objLaser = CreateCurveLaserA1(ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 4, GetAngleToPlayer(bossObj), 60, 18, DS_SCALE_WHITE, 10);
let playerX = GetPlayerX;
let playerY = GetPlayerY;
ObjMove_AddPatternA2(objLaser, 5, 1, NO_CHANGE, 0, 1, 50);
ObjMove_AddPatternA2(objLaser, 25, 1, NO_CHANGE, 0.1, -1, 2);
wait(60);
ObjMove_SetDestAtFrame(objLaser,playerX,playerY,20); // Aim to player
deleteIn(objLaser,120); // Delete in 2 seconds
changeBullets(playerX, playerY) // Affect the bullets
}
}
task changeBullets(x,y)
{
wait(60);
let bullets = GetShotIdInCircleA1(x,y,99999);
ascent(i in 0..length(bullets))
{
ObjMove_SetAngle(bullets[i], GetAngleToPlayer(bullets[i]));
Obj_Delete(bullets[i]);
}
}
Sorry if the post wasn't clear, I was experimenting with my post.
So my spell spawn rings of bullets from the boss. She will also occasionally fire curved lasers aiming for the player.
When the laser reaches the target position they will make all the bullets around the area of landing, aim towards the player. The snippet is the function that gets the bullets and makes them aim.
I removed the offending lines of code but it still doesn't work. I'll include more of the script:Code: [Select]task fire02
{
while(true)
{
let objLaser = CreateCurveLaserA1(ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 4, GetAngleToPlayer(bossObj), 60, 18, DS_SCALE_WHITE, 10);
let playerX = GetPlayerX;
let playerY = GetPlayerY;
ObjMove_AddPatternA2(objLaser, 5, 1, NO_CHANGE, 0, 1, 50);
ObjMove_AddPatternA2(objLaser, 25, 1, NO_CHANGE, 0.1, -1, 2);
wait(60);
ObjMove_SetDestAtFrame(objLaser,playerX,playerY,20); // Aim to player
deleteIn(objLaser,120); // Delete in 2 seconds
changeBullets(playerX, playerY) // Affect the bullets
}
}
task changeBullets(x,y)
{
wait(60);
let bullets = GetShotIdInCircleA1(x,y,99999);
ascent(i in 0..length(bullets))
{
ObjMove_SetAngle(bullets[i], GetAngleToPlayer(bullets[i]));
Obj_Delete(bullets[i]);
}
}
Firstly, I recommend reading the description of GetShotIdInCircleA1: https://dmf.shrinemaiden.org/wiki/Shot_Functions#GetShotIdInCircleA1It works! Thanks.
You should probably use GetShotIdInCircleA2 with TARGET_ENEMY.
Secondly, changeBullets(playerX, playerY) is based on the player's location, not that of the laser. Keep that in mind.
Rawcode Here:
Is there a way to detect what graphic is a bullet. Or better yet some way to "Tag" a bullet and read that tag?
Thanks.
What exactly are you trying to do? Both you as the scripter and the players who are playing your game should always be able to know what graphic is a bullet. In your case, you know on a code level because any graphic that's not boss/player/effect/etc. is going to be a bullet (and you as the scripter decide where the bullet are and where they go), while for the player, if they can't distinguish what is and is not a bullet, they're not going to have a fun time playing your script.Ah Thanks. And I'm sorry if the lack of information is impairing your ability to help me effectively, Next time I'll state my goal.
In short, you are creating the bullets. Therefore, you always know which graphic is a bullet and which one is not. If you are trying to get the graphic corresponding to a bullet, use https://dmf.shrinemaiden.org/wiki/Shot_Object_Functions#ObjShot_GetImageID
In the future, please refer to the tutorials and wiki function list to see if your question can be answered with an existing function. Also, it is important to state what you are trying to achieve, so that we can assist you more effectively.
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["Koishi Komeji"]
#Text["Koishi is acting up again"]
let dir = GetCurrentScriptDirectory();
let obj = ObjEnemyBossScene_Create(); // Make the boss scene object
@Initialize
{
SetCommonData("ScriptID", GetOwnScriptID());
TPlural;
}
@Event
{
alternative(GetEventType)
case(EV_USER)
{
ObjEnemyBossScene_StartSpell(obj);
ObjEnemyBossScene_LoadInThread(obj); // Load
}
}
@MainLoop
{
yield;
}
task TPlural
{
// Define Scripts
ObjEnemyBossScene_Add(obj, 0, dir ~ "non01.txt");
ObjEnemyBossScene_Add(obj, 0, dir ~ "spell01.txt");
ObjEnemyBossScene_LoadInThread(obj); // Load
ObjEnemyBossScene_Regist(obj); // And register
while(!Obj_IsDeleted(obj)){yield}; // yield while the Boss is not deleted
CloseScript(GetOwnScriptID()); // Close if it the boss died
}
function GetCenterX(){
return GetStgFrameWidth() / 2;
}
function GetCenterY(){
return GetStgFrameHeight() / 2;
}
It's me Again!
So I'm trying to load the next scene in a Boss Scene object, but my attempts have come up futile. I have no Idea on how to do it. Can you help me?Code: [Select]
Thanks.
I don't know what exactly you are trying to accomplish here, but here's what I recommend:Sorry, I thought I clarified more. So I want to load the next stage after the boss's health bar reaches 0. All it did was well... nothing.
Please refer to http://sparen.github.io/ph3tutorials/ph3u2l12.html
You are misusing a number of functions as well. https://dmf.shrinemaiden.org/wiki/Functions_(ph3)#Boss_Scene_Object_Functions
ObjEnemyBossScene_StartSpell is meant to be used in the Single scripts. There is no need to use any fancy notify events since GetEnemyBossSceneObjectID() can be used in a Single script to retrieve the Boss Scene object ID.
If there are issues with my guide (i.e. it's not clear on what to do or there is something missing), please let me know.
I can't say for sure what's going wrong without seeing at least some of your code, unfortunately. Note that, for Reimu's homing amulets, you probably want a task for each individual bullet where it homes in on the enemy closest to it when it spawned. IIRC, there was a nice example of such a task near the very start of this thread.Here's all that i used for shots. https://pastebin.com/i2ZH77sZ
Sorry, I thought I clarified more. So I want to load the next stage after the boss's health bar reaches 0. All it did was well... nothing.
I did look at your guide and the functions, but it didn't give me what I need.
Hello, does anyone know how to make homing player shots, just like Reimu's amulets? I almost did it myself, but i cant find the right way to target the closest enemy, the shots always target the one that spawned first
For each shot, calculate the distance between the shot and the enemies using the Distance Formula, then lock onto the closest one.
let fairyTex = "././Sprites/spr_Fairy01.png";
let red = 0;
function MakeFairy(life, x, y, colour)
{
let obj = ObjEnemy_Create(OBJ_ENEMY); // Make Fairy
ObjEnemy_Regist(obj); // Start Fairy
ObjEnemy_SetLife(obj, life); // Set Life
ObjEnemy_SetIntersectionCircleToShot(obj, 0, 0, 20); // Set Shot Collision
ObjEnemy_SetIntersectionCircleToPlayer(obj, 0, 0, 20); // Set Player Collision
//FairyLoop(obj, colour); // Start loop
ObjMove_SetPosition(obj,x,y); // Set Fairy Position
return obj;
}
task FairyLoop(fairy, colour)
{
let frame = 0;
let rate = 30;
ObjPrim_SetTexture(fairy,fairyTex); // Set Texture
ObjSprite2D_SetDestRect(fairy,0,0,32,32); // Set Center
ObjSprite2D_SetDestCenter(fairy); // Set Center
while(!Obj_IsDeleted(fairy)) // While Fairy is not Deleted.
{
frame++; // Increment Frame
if(frame < rate) // Frame 1
{
ObjSprite2D_SetSourceRect(fairy, 0, colour, 32, 32 + colour);
}
else if(frame > rate && frame < rate * 2) // Frame 2
{
ObjSprite2D_SetSourceRect(fairy, 32, colour, 64, 32 + colour);
}
else if(frame > rate && frame < rate * 2) // Frame 3
{
ObjSprite2D_SetSourceRect(fairy, 64, colour, 96, 32 + colour);
}
if(frame > rate * 4){frame = 0;} // Loop Frame if...
yield;
}
}
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["testinging"]
#Text["testing"]
#include "./Library/lib_FairyF.dnh"
#include "./Library/lib_Misc.dnh"
#include "script/default_system/Default_ShotConst.txt"
// Default Functions
@Initialize // Called At Start
{
MakeFairy(0,GetCenterX,GetCenterY,0);
mainTask; // Call Main Task
}
Okay, this problem has been driving me crazy. I keep getting this error: 敵ライフを適切に返していません。
(snip)
Okay, this problem has been driving me crazy. I keep getting this error: 敵ライフを適切に返していません。
...
I have tried even commenting everything in lib_FairyF but I still get the error:
Why don't you try turning your Single script into a Stage script instead? I'm not sure what goes on in mainTask;, so I can't really say anything else about test.txt for certain, but I'm guessing you may have removed the information from @Event that takes care of the boss's life. With a Stage script, you can handle fairies without necessarily having to handle a boss.
Firstly, you're setting the enemy's life to 0, and its hitbox only appears for one frame at the top left corner of the screen.
Secondly, the issue is that you're unable to GET the fairy life. Which line does the error appear at in which script, and how are you trying to access the enemy's life at that location? The fact that you can comment out the entire library and still get the error leads me to believe that the cause of the error is outside the library.
let ITEM_PENDULUM = 1;
@Initialize{
SetDefaultBonusItemEnable(false);
let dir = GetCurrentScriptDirectory();
LoadItemData(dir~"item_data.dnh");
}
@MainLoop{}
@Event{
alternative(GetEventType())
case(EV_USER+72){
let pos = GetEventArgument(0);
if(length(pos) == 2){
TItem(ITEM_PENDULUM, pos[0], pos[1]);
}
}
case(EV_GET_ITEM){
let type = GetEventArgument(0);
let item = GetEventArgument(1);
alternative(type)
case(ITEM_PENDULUM){
SetPlayerSpell(GetPlayerSpell() + 1);
}
}
case(EV_DELETE_SHOT_TO_ITEM){
let shot = GetEventArgument(0);
let pos = GetEventArgument(1);
TItem(ITEM_PENDULUM, pos[0], pos[1]);
}
}
task TItem(type, x, y){
let obj = CreateItemU1(type, x, y, 0);
Obj_SetRenderPriorityI(obj, 60);
}
Hi. I am trying to play this script, but ph3 always freezes... Anybody know what's the problem? ( I assume that it is related to infinite loop )You didn't yield your while loop which starts at line 64
https://pastebin.com/DLyLwi8Z
You didn't yield your while loop which starts at line 64
Not really, but I found a rough explanation for the basic implementation and usage of item scripts I made a while ago: https://www.shrinemaiden.org/forum/index.php/topic,16584.msg1108259.html#msg1108259
Here is an example of a simple item script I'm using:
Which honestly isn't much different than what's posted in the above link, but is filled with actual data. This is also an item script for player-specific items and not connected to a full game with many items, so you should look for other examples (it shouldn't be much different than just having many item cases and extra behaviour).
I don't know if I'll be able to explain this right, please bear with me :V
I want to fire a curvy laser at a constant speed and angular velocity(probably 3 and 1 but I might change it) but I want it to go through the player's current position no matter where on the screen. To do that I'd need a way to calculate an angle for it to be fired based on its position, speed, angular velocity and the player's position, how can I do that?
If you want the laser to fly only in one direction (like a regular shot) you can set its angle using GetAngleToPlayer, ang then just make it look curvy with another task. But if you want it to follow the player, that would require some complicated calculations, which i dont knowIt's pretty crazy, so let me explain again. I want the laser to PASS THROUGH the player's position when it's fired, so that it will hit them directly unless they dodge, no matter where on the screen. The speed and angular velocity will be constant(3 and 1, though I might change them).
It's pretty crazy, so let me explain again. I want the laser to PASS THROUGH the player's position when it's fired, so that it will hit them directly unless they dodge, no matter where on the screen. The speed and angular velocity will be constant(3 and 1, though I might change them).
I don't know if I'll be able to explain this right, please bear with me :V
I want to fire a curvy laser at a constant speed and angular velocity(probably 3 and 1 but I might change it) but I want it to go through the player's current position no matter where on the screen. To do that I'd need a way to calculate an angle for it to be fired based on its position, speed, angular velocity and the player's position, how can I do that?
1. Since some danmakufu patterns require trigonometry, can you...I'm just going to post a bunch of links for this one
?Teach me how to harness the power of trigonometry myself (Note: I already went to Sparen's Danmakufu Tutorial site to figure it out but it seems very hard to pull off if you want to do it yourself, especially if you don't have a graphing calculator or how to plug it into the script itself)
?Give me just few examples of trigonometry in action in Danmakufu (this is optional)
2. I've noticed that Imperishable Night bosses use a lot of spell circle shaped familiars to shoot for them. ESPECIALLY Marisa in stage 4. Can you possibly teach me how to summon said familiars in Danmakufu so I can incorporate it in my own scripts?
I'm just going to post a bunch of links for this one
?Khan Academy (learning trig in case you are unfamiliar with the basics)
https://www.khanacademy.org/math/trigonometry
?Parametric Equations and various curves (Example equations, etc)
https://sites.math.washington.edu/~aloveles/Math124Fall2017/m124ParametricEquationsIntro.pdf
http://www-history.mcs.st-and.ac.uk/Curves/Curves.html
Well you answered my second question quite nicely, but I was wondering how to actually PLUG IN the equations in a Danmakufu script. Say I would want to implement the Devil's Curve pattern for my shots (http://www-history.mcs.st-and.ac.uk/Curves/Devils.html) how would I go about that?
CreateShotA1(GetEnemyX(objBoss)+120*cos(angleT*3), GetEnemyY(objBoss)+90*sin(angleT*5), 1, angleT*3, graph, 0);
task DevilCurve{
let t = 0;
// Control the curve parameters
let a2 = 1;
let b2 = 2;
// Control the scaling parameters
let scalex = 64;
let scaley = 64;
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0) {
let s_num = a2*sin(t)*sin(t) - b2*cos(t)*cos(t);
let s_denom = sin(t)*sin(t) - cos(t)*cos(t);
let s_all = (s_num/s_denom)^0.5;
CreateShotA2(ObjMove_GetX(objBoss) + scalex*cos(t)*s_all, ObjMove_GetY(objBoss) + scaley*sin(t)*s_all, 0, t*2, 0.01, 3, DS_BALL_BS_SKY, 10);
t++;
yield;
}
}
Above, I've used three variables (s_num, s_denom, and s_all) for sanity purposes, as the mess under the square root is hard to check for errorsfunction BulletCircle(X, Y, angle, radius, numBullets) {
let increment = 360/numBullets;
ascent(i in 0..numBullets){
if(Obj_IsDeleted(bossObj)){return;} //Prevents bullets from spawning after the script finishes
let obj = CreateShotA1(X+radius*cos(i*increment),Y+radius*sin(i*increment),3,angle,DS_RICE_S_YELLOW,30);
}
}
function CreateShotShapeA1(x, y, shape_sides, shape_gap, shape_radius, shape_angle, speed, angle, graphic, delay){
let shots = [];
let t = 0;
while(t < 360){
let r = cos(180/shape_sides) / cos(((t - shape_angle) % (360/shape_sides)) - (180/shape_sides));
if(shape_radius == 0 && angle == 0){
// expand shape from center
shots = shots ~ [CreateShotA1(x, y, r * speed, t, graphic, delay)];
}else{
// fire shape in direction
shots = shots ~ [CreateShotA1(x + shape_radius*r*cos(t), y + shape_radius*r*sin(t), speed, angle, graphic, delay)];
}
t += shape_gap;
}
return shots;
}
// expand
CreateShotShapeA1(192, 150, 5, 4, 0, 90, 2, 0, SHOT_RING_RED, 10);
// shoot
CreateShotShapeA1(192, 150, 4, 4, 80, 115, 2, 70, SHOT_RING_RED, 10);
function BulletCircle(X, Y, angle, radius, speed, numBullets, graph, del) {
let increment = 360/numBullets;
ascent(i in 0..numBullets){
if(Obj_IsDeleted(objBoss)){return;} //Prevents bullets from spawning after the script finishes
let obj = CreateShotA1(X+radius*cos(i*increment),Y+radius*sin(i*increment),speed,angle,graph,del);
}
}
I actually changed a bit of Arc's code so I can mess with the speed, delay and graphic. I have another request, I want to LEARN (NOT JUST PASTE THE CODE) how to make Non-Directional Lasers like Alice in SWR/Soku
Crimson Sign "Holland Doll"I know that Sparenoflria alrady did a tutorial of how to make Non-Directional Lasers, but it almays ended doing 4-way lasers
Plz help
Basically, you define multiple sound objects in the plural script itself and then run a task in that script that detects which phase the boss fight is on and changes which sound object is playing accordingly. You probably want to fade out the old music instead of just having it end abruptly.
Could you explain it with codes, beacuse it's confusing for me to understand.
let cur_music = ""; // globally (or high-level) scoped
objSound_Music = ObjSound_Create();
ObjSound_SetSoundDivision( objSound_Music, SOUND_BGM );
// Play the music, fading the previous in fade_time seconds
task PlayMusic( let path_to_music, let fade_time )
{
if( cur_music != path_to_music ) // applies only when changing music
{
let cur_volume = ObjSound_GetVolumeRate( objSound_Music );
let fade = -cur_volume / fade_time;
ObjSound_SetFade( objSound_Music, fade );
while( ObjSound_GetVolumeRate( objSound_Music ) > 0 ){ yield; } // wait until fade is done before proceeding
cur_music = path_to_music;
ObjSound_Load( objSound_Music, path_to_music );
ObjSound_SetVolumeRate( objSound_Music, 100 );
ObjSound_Play( objSound_Music );
}
}
function ObjSound_PlayForceRestart(obj){
ObjSound_SetRestartEnable(obj, false);
ObjSound_Play(obj);
ObjSound_SetRestartEnable(obj, true);
}
You can set a BGM sound object restarting to true by default and play it normally, and then when you need to start from the beginning you can set restarting to false, Play, and set it back to true again. You could make it a function likeThis has worked indeed. And that's what I've been doing, but my problem was that I tried to use something similar while stopping music (so that I could simply use ObjSound_Play the next time).Code: [Select]function ObjSound_PlayForceRestart(obj){
ObjSound_SetRestartEnable(obj, false);
ObjSound_Play(obj);
ObjSound_SetRestartEnable(obj, true);
}
Unfortunately you can't get what the setting was to begin with so you would have to assume it was initially set to true.
Please be patient
http://www.bulletforge.org/u/darkwalker247/p/stellar-effects-library (http://www.bulletforge.org/u/darkwalker247/p/stellar-effects-library) - Stellar FX
http://www.bulletforge.org/u/darkwalker247/p/bloom-effects-library-now-events-based (http://www.bulletforge.org/u/darkwalker247/p/bloom-effects-library-now-events-based) - BFX
----------------------------------------------------------------------------------------------------------------------------------------------------
Both of them are/have functions to make your script more serious (I would say), putting effects and Magic Circles around the boss...
I only have three questions:
(1) Which one is the easiest?
(2) Is there any tutorial about this on any site?
(3) If there isn't or it's not updated anyone could someone explain how to do this?
They are function libraries - include what you need to and use what you want to. There are no tutorials since the instructions on Bulletforge explain what you need to do to use the library - #include what you need to, call the functions you want to call.My question was how to use it the library, beacuse I couldn't know what was I doing(what value should I use, what this variable do, the range I should put, etc.)
For example, if I wanted to use the former, I'd #include Stellar.dnh at the top of my Single script, and in @Initialize I would call Stellar_Init(). Afterwards, I would call whatever function I wanted to.
Stellar_Init() --Call this once before all other functions.
Stellar_ParticleTexture(path) --Set the texture to use for particles; this can be changed at any point without affecting particles already out so it's okay to change texture a lot.
Stellar_AuraTexture(path) --Set the texture to use for the "aura" effect; this can be changed at any point as well.
Stellar_MagicCircleTexture(path) --Set the texture to use for magic circles; this can be changed at any point as well.
Stellar_AuraPriority(priority) --Set the render priority for the "aura" effect; an integer between 0 and 100.
Stellar_MagicCirclePriority(priority) --Set the render priority for the magic circle effect; an integer between 0 and 100.
Stellar_Explosion(object,time,particlescale,blending,hue) --Create a 3D explosion effect with particles.
Stellar_Charge(object,time,particlescale,blending,hue) --Create a 3D charge effect with particles.
Stellar_Aura(object,radius,wavelength,rotspeed,fadetime,blending,hue,saturation) --Create an "aura" effect that is a warping rotating textured circle around the object.
Stellar_Emitter(object,time,scale,speed,firepitch,fireyaw,spread,life,numperframe,blending,hue,saturation,alpha) --Create a 3D particle emitter on an object.
Stellar_MagicCircle(object,scale,fadetime,pulseamount,pulsespeed,angvel,blending,hue,saturation,alpha) --Create a magic circle on an object.
How do I upload my scripts?
I can't register to the BulletForge, so I want to know if that problem is my fault, or if is the site's fault.
(And how to solve this)If it's my fault= What's the problem? My country? My net? My browser?If it's the site's fault= What should I do then? Contact the author?Poste it in another site?
From what I've heard Bulletforge has closed signups so you'd need to contact the owner to get an account.
In the meantime just upload to any file sharing site (preferably one that isn't a scam) and share the link.
How can I make the bullets transforms to score(that gray squares that add to your score)?use DeleteShotAll( ,TYPE_ITEM)
So, I want to reveal parts of background only in certain places and shapes, kinda like Doremy's occult attack in AoCF (http://tinypic.com/r/33m9b2d/9), how do I do it? I tried using render targets, but it's too complicated and difficult to use without a tutorial.
Btw, how do I attach images to my posts?
While it's actually pretty easy (or not, depending on how much setup you're comfortable with doing from scratch) to grab simple shapes from a texture and draw them in Danmakufu, the same may not hold true if you want to take the transparency of the edges of the shapes into account, in order to preserve a more natural-looking portal effect as is done in the example from Antinomy of Common Flowers that you had provided.
You're better off creating an alpha mask and using HLSL to display part of an image with the transparency dictated by the alpha mask. If you want to display an animated image, you may also try passing the name of a render target to the shader, since a render target may be updated without having to reset the texture taken by the objects that use said render target each frame.
There is an example in the script/sample folder that demonstrates just that. I think it's shader example #2, but my memory could be failing me. Please consult them -- the simple act of (methodical) experimentation and learning through trial and error will prove to be very useful.
Or DeleteShotInCircle.How can I make the bullets transforms to score(that gray squares that add to your score)?use DeleteShotAll( ,TYPE_ITEM)
What are the AnimationData arguments? (I couldn't find it on dmf wiki)(num_frames, left, top, right, bottom)
Is there a function for making the screen shake like Master Spark?You can use Set2DCameraFocusX and Set2DCameraFocusY to shift the 2D camera around. Then you would write something that uses those to move the camera rapidly.
I followed your advise and used 2nd sample, but now I have even more problems. Using different images as masks and applying them to different render priorities is ok, but I don't know how to manipulate the masks (change their scale, etc.), and I don't know neither how shaders work in danmakufu nor HSLS programing, and that makes it really hard for me. Is there any tutorials on danmakufu shaders and maybe HLSL that doesn't require deep C++ knowledge?Shader objects are Render objects and so you can use things like ObjRender_SetScaleXYZ as you would anything else.
Shader objects are Render objects and so you can use things like ObjRender_SetScaleXYZ as you would anything else.
Here's all the code that I use (https://pastebin.com/YzMNJQ1j - danmakufu code; https://pastebin.com/wuCby6mg - HLSL code), but none of the ObjRender functions work on objShader. Maybe I'm missing something?Haven't forgotten about this, but yes in order to do what you want you need some extra stuff. I have a test background I did this with, but there's a lot of unrelated code so it's a bit tricky to extract just the parts needed to explain what to do, so hang on.
Relevantly, the fact that you're deleting the dummy shot from its own task should clue you in that you don't really need the dummy at all. The main benefit that returning a dummy shot object carrying the shot array has over just returning the shot array is that, if you want to change the array over time from an internal task, you can't just pass the array reference (because arrays are not mutable), so you use the mutable object instead. But in your case you aren't using the returned object at all, nor is the object being used in the task because it's just a dummy anyways. So really "Shots" and "IsNewShots" should just be variables.Normally I would just return the shot array, yes, but in this case not all the bullets are created immediately, so I'd only get an array containing the first bullet and not be able to get a reference to the others. By doing it like this I can come back and grab the references once all the shots have been created, or handle the new ones as they're created. I'm not using it for anything at the moment, but I almost certainly will at some point, so it's there when I need it.
Haven't forgotten about this, but yes in order to do what you want you need some extra stuff. I have a test background I did this with, but there's a lot of unrelated code so it's a bit tricky to extract just the parts needed to explain what to do, so hang on.You mean the gaps? They're shaping up pretty nicely, actually. Here's the current code: https://pastebin.com/VgTfDrTz
Normally I would just return the shot array, yes, but in this case not all the bullets are created immediately, so I'd only get an array containing the first bullet and not be able to get a reference to the others. By doing it like this I can come back and grab the references once all the shots have been created, or handle the new ones as they're created. Deleting it from the task is just to make sure it gets deleted, since it's not autodelete and isn't moving anyway - the idea is I'd copy the final array before it's deleted - but now that I look at it again there are better ways of ensuring that.Well like I said, you don't actually seem to be using the return value for anything. Even if you did want to use the returned dummy object, you delete it, making it useless.
You mean the gaps?I quoted somebody else, if you missed that ;P
Well like I said, you don't actually seem to be using the return value for anything. Even if you did want to use the returned dummy object, you delete it, making it useless.It waits a few seconds after creating all the bullets to delete it, so I can grab a new reference before then. It is a bit silly, though, I'll probably rework it before actually using it.
If you plan to actually use the array outside of the task, what you can do instead is to not use CreateShotA1, but create and set up the shots manually, all at once, but have each row of bullets call ObjShot_Regist (i.e. fire them) after a different number of frames. This way all the objects are created and can fill the array which you can then return.Ah, so that's what that's for! I kept seeing those and not quite getting why I would use them instead of the CreateShot functions. I'll have to mess around a bit with that, then.
Here's my implementation: https://gist.github.com/drakeirving/36aac5ad8ddcc504525a983d56a3e2eaRandom question, is there any particular reason you're allocating space for the reference to the shot in the loop itself? I usually put let shot, etc before the loop, so I can reuse the same variable and in theory save time on memory allocation.
I quoted somebody else, if you missed that ;PAh, whoops. I hit quote and was looking at that when typing out my response.
Random question, is there any particular reason you're allocating space for the reference to the shot in the loop itself? I usually put let shot, etc before the loop, so I can reuse the same variable and in theory save time on memory allocation.Nah, no particular reason. Garbage collection works fine; it isn't as though the actual objects are allocated differently either; the ID is just a number. When it has a coding advantage I'll typically opt for it.
On the other hand, I hadn't realized that you can avoid passing things in as arguments to those internal tasks like that, at least inside a loop. I always passed in i manually. Does the task need to be defined inside the loop to do that?
task TPlural{
if(first_bosslife == 0) {
create(second_boss);
change(bgm1 to bgm2);
}
}
If you wanted to fight two bosses back-to-back you would make a stage with two plural scripts. A plural script generally (but doesn't have to) contains one boss.
Also see http://sparen.github.io/ph3tutorials/ph3u3l23.html
Threw together an example of two plural scripts in the same stage at the end of the guide.Thank you for this adding this.
If you wanted to fight two bosses back-to-back you would make a stage with two plural scripts. A plural script generally (but doesn't have to) contains one boss.It worked perfectly and I thank you very much, but I'm having problem with the background and exiting (before reaching the boss - "you are using a variable that has not been set yet")
Also see http://sparen.github.io/ph3tutorials/ph3u3l23.html
After recent drivers update, all Danmakufu ph3 based games, includind ido games from MPP to BSM, became crash on start. Debugging shows that the problem is in the amd64 driver. Does anyone except me has such problem?
The problem seems to be that stagepart isn't set to a value when its created, but can be checked by @Event before it gets a value assigned to it. If you changed line 7 from "let stagepart" to "let stagepart = 0", then it should probably work fine.The error is gone, thanks for the help :D
The error is gone, thanks for the help :D
But... the background is still black...and I don't know why
task TCallBg{
loop{
TNormalBackground;
while(bSpell==false){ yield; }
TSpellBackground;
while(bSpell==true){ yield; }
}
}
function isnull(obj){ //is this safe to use?
//do something //if it hasn't been set
if(!obj){return true;} //if it's null
if(Obj_IsDeleted(obj)){return true;} //if it's been deleted
return false; //we're good
}
Almost definitely the problem is that you start it immediately with TCallBg which checks while(!Obj_IsDeleted(GetEnemyBossSceneObjectID())). In a Single or Plural, the boss scene object will exist before your script even starts (because it's created in the "default" stage script), but in a Stage script it won't exist until you start a plural script where you make the scene object. So the while loop condition fails immediately and your background is never created.
You can fix this by changing TCallBg to something else that makes sense for the stage. How it's set up right now (draw a normal bg until a spell starts, then draw the spell bg until it stops, and loop as long as the boss exists) is clearly meant for a boss fight, but if you actually had stuff before or after the boss, this doesn't make sense anymore.
Because your MainLoop already does the checking for an existing boss scene and spell (and puts the result in bSpell), you can actually make it simpler:Code: [Select]task TCallBg{
loop{
TNormalBackground;
while(bSpell==false){ yield; }
TSpellBackground;
while(bSpell==true){ yield; }
}
}
I'm trying to write a function to safely check if a variable is null, deleted, or otherwise shouldn't be dereferenced. It can check both of those fine, but doing so 100% safely is out of reach unless I can find a way to check if it's been set.I don't think this is ever possible. If your intended use is to set up variables meant to store object IDs but have them potentially empty, or want to empty them, and still have all processing work consistently, you should be setting the values to ID_INVALID, which is just -1.
Is there any possible way to check if a variable has been set without crashing the script? Exception handling, awful hacks, anything?
I know it's really simple to do these desires, but I can't figure it out how to do them:
- Write the name of the boss below the lifebar
- Have an difficulty written (not with CommonData)
- Have pretty effects(like charge, death, explode)
ObjText_SetFontType(text, "./reve.ttf");
//or
ObjText_SetFontType(text, Revue);
About fonts
I have a file named "reve.ttf" which font is Revue...but...
Which example should I use?Code: [Select]ObjText_SetFontType(text, "./reve.ttf");
//or
ObjText_SetFontType(text, Revue);
The font name is Revue. Use Revue.oops forgot InstallFont
...I guess I should directly spell this out in my tutorial, huh.
Is there a way to extract archives from .dat files?
If a creator decides to package their files so that they cannot be accessed by other people, please respect their decision to protect their assets.
If you want to rip their resources with complete disregard to their wishes, feel free to use Google search or the forum's search feature.
task MainTask {
Wait(60); //Time for the Boss to get in position
while(ObjEnemy_GetInfo(objBoss,INFO_LIFE) > 0){
let bomb = CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 0, 90, DS_BILL_BLUE, 5); //Creates "Bombs"
ObjMove_SetDestAtFrame(bomb, GetPlayerX(), GetPlayerY(), 60); //Moves the "Bomb" to the Player's previous position
Wait(60); //Wait until the bomb gets in position
let thetaT = rand(0,36);
ascent(i in 0..10){
let bull = CreateShotA1(ObjMove_GetX(bomb), ObjMove_GetY(bomb), 4, thetaT+36*i, DS_BALL_M_A_SKY, 5); //Creates the "shrapnel"
ObjMove_SetAngularVelocity(bull, 0.45);
ascent(j in 0..10){
let orb = CreateShotA1(ObjMove_GetX(bull)+20*cos(36*i), ObjMove_GetY(bull)+20*sin(36*i), 0,36*j, DS_BALL_SS_SKY, 5); //Creates bullets that circle around the shrapnel
Orbit(bull,orb,36*j);
}
}
Obj_Delete(bomb); //Deletes the bomb
Wait(7);
}
}
task Orbit(bull,orb,ang) {
let tim = 0;
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){
ObjMove_SetPosition(orb,ObjMove_GetX(bull)+4.3*cos(ObjMove_GetAngle(bull))+20*cos(ang+tim), ObjMove_GetY(bull)+4.3*sin(ObjMove_GetAngle(bull))+20*sin(ang+tim)); //Keeps the bullets around the shrapnel
tim += 3; //Causes the bullets to rotate around the shrapnel
yield;
}
}
The problem I'm having is that tiny bullets keep appearing in the top-left corner. I think it's the SetPosition command in the Orbit task that's causing this, but I don't know how to fix it.I wanted to make an overlay that moves/scroll above the spell bg...
How I do that?
How can I recreate Reisen's effect/illusion?
("one" bullet turns to two in differents angles - First Spell)
function lerp(start,end,t){return (1-t)*start+t*end;}
function blerp(x0,y0,x1,y1,t){return [lerp(x0,x1,t),lerp(y0,y1,t)];}
These are functions for [bi]linear interpolation, which just means "get a point xx% of the way along this line". The first is for a single value (such as x, y, or angle); the second finds a point in 2D coordinates. t is a ratio (0-1) of how far along to get the point from.//Ultima
function NormalizeAngle(angle){ angle %= 360; if(angle<0){angle += 360;} return angle; }
//Blargel
function GetAngularDistance(angle1, angle2){ let distance = NormalizeAngle(angle2 - angle1); if(distance>180){ distance-=360; } return distance; }
These help avoid things behaving weirdly when, say, one angle is 15 degrees and the other is 330 degrees. If you just subtract the angles normally it'll probably end up going all the way around - this way you can easily determine the shorter way to turn.task MoveShot(shot,startx,starty,endx,endy,startang,endang,time){
ObjRender_SetAlpha(shot,128); ObjShot_SetIntersectionEnable(shot,false); let origspd = ObjMove_GetSpeed(shot);
let dA = GetAngularDistance(startang,endang);
let pos; let ang;
ascent(i in 0..time){
pos = blerp(startx,starty,endx,endy, i/time);
ang = startang + lerp(0,dA, i/time);
ObjMove_SetPosition(shot, pos[0],pos[1]);
ObjMove_SetAngle(shot,ang);
yield;
}
ObjRender_SetAlpha(shot,255); ObjShot_SetIntersectionEnable(shot,true); ObjMove_SetSpeed(shot,origspd);
}
You'd call that on both the original shot and the copied shot, adjusting their parameters as desired.
The problem here is that you aren't checking if the central bullet has been deleted. The central shot gets deleted, the task keeps going, and it continues setting the orbiting shots' position. Since the central shot is deleted, trying to get its position gives 0,0, and so that's where they rotate around. Rather than while(ObjEnemy_GetInfo(objBoss,INFO_LIFE)>0){...}, use while(!Obj_IsDeleted(bull)){...}.Code: [Select]while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){
ObjMove_SetPosition(orb,ObjMove_GetX(bull)+etc, ObjMove_GetY(bull)+etc);
yield;
}
Make an Overlay, and then move it across the spell bg using ObjRender_SetPosition()?Don't worry, I got it working with "your" help (your github site)
So the code to move the shot would look something like this:Thank you very much for this, that was too complex for me to think about alone, but how I do this in a circle?Code: [Select]task MoveShot(shot,startx,starty,endx,endy,startang,endang,time){
ObjRender_SetAlpha(shot,128); ObjShot_SetIntersectionEnable(shot,false); let origspd = ObjMove_GetSpeed(shot);
let dA = GetAngularDistance(startang,endang);
let pos; let ang;
ascent(i in 0..time){
pos = blerp(startx,starty,endx,endy, i/time);
ang = startang + lerp(0,dA, i/time);
ObjMove_SetPosition(shot, pos[0],pos[1]);
ObjMove_SetAngle(shot,ang);
yield;
}
ObjRender_SetAlpha(shot,255); ObjShot_SetIntersectionEnable(shot,true); ObjMove_SetSpeed(shot,origspd);
}
Ah, right, I originally came here to ask a question of my own.You'll have the frame of difference if the second object position is set before the first object moves (generally because the tasks were started and yielded in that order), or if the first object moves using SetAngle/Speed or similar functions, which only updates positions after the frame is over but before rendering (not that this is relevant for Sprite objects). If it's the first and you can't guarantee execution order, you could use an auxiliary position variable that both objects will move to.
I've got (among other things) a 2D sprite that goes on top of another 2D sprite, and a task setting its position to the position of the first one. When I move the first one around, though, the second lags behind by a frame, presumably due to the order things are being executed in each frame. Any way I can synchronize them aside from moving both of them every time?
Thank you very much for this, that was too complex for me to think about alone, but how I do this in a circle?If you mean moving the shot in (part of) a circle, you'll want to pick a center point to rotate around, and use lerp for the angle from the center. Something like:
rad=getdist(cx,cy,startx,starty); startarc=getangle(cx,cy,startx,starty); endarc=getangle(cx,cy,destx,desty);
arc=lerp(startarc,endarc,i/time); x=cx+rad*cos(arc); y=cy+rad*sin(arc);
function getangle(x0,y0,x1,y1){return atan2(y1-y0,x1-x0);}
function getdist(x0,y0,x1,y1){return ((x0-x1)^2 + (y0-y1)^2)^0.5;}
I don't think that's what you meant, so I crunched it up to save space, but it's there if you did mean that. Grab those functions either way if you haven't got them, though.The result is only one bullet(or 60 in one position?)Er, yes, you call that on each copy of the original shot, it doesn't make the copies. Try this instead:
MoveShot(s, ObjMove_GetX(s), ObjMove_GetY(s), ObjMove_GetX(s) - 50, ObjMove_GetY(s), 0, 0, 60);
let N=60; let radius=50;
ascent(i in 0..N){
s = CopyShot(origshot); //or whatever you're doing to copy them
MoveShot(s, ObjMove_GetX(s), ObjMove_GetY(s), ObjMove_GetX(s)+radius*cos(i*360/N), ObjMove_GetY(s)+radius*sin(i*360/N), ObjMove_GetAngle(s), ObjMove_GetAngle(s), 60);
}
Here's the function I use to copy shots (https://pastebin.com/vbseDHzt), or you can just create the same kind of shot with the original shot's position/angle/etc.Andi: You're definitely talking too high-level there, just saying. You might not be able to help much.Whoops, tried to tone it down a bit.
do A, yield, do B, yield, do A, ...and so on.
How can I implement this thing with codes?
loop(600){ do A; yield; }
wait(60);
loop(540){ do B; yield; }
wait(60);
Or how I usually do it:let thingtodo=A;
task TdoA { while(thingtodo==A){ do A; yield; } wait(60); TdoB; }
task TdoB { while(thingtodo==B){ do B; yield; } wait(60); TdoA; }
task ChangeThingToDo{
TdoA;
loop{
wait(540); if(thingtodo==A){thingtodo=B;}else{thingtodo=A;}
}
}
My mind was just tangled with if statements and the frame.You already have the logic fine. I'm not entirely sure what's troubling you.
What I was trying to do was below:
loop{ // or while(something), etc
loop(600){
// A
yield;
}
loop(60){ yield; }
loop(540){
// B
yield;
}
}
task BulletA{
// make the bullet here
ObjShot_SetSpellResist(obj, true);
while(!Obj_IsDeleted(obj)){
DeleteShotInCircle(TYPE_SHOT, TYPE_IMMEDIATE, ObjMove_GetX(obj), ObjMove_GetY(obj), deletion_radius);
yield;
}
}
That problem starts easy enough but can get really complicated depending on what you actually want. If you just want A bullets that erases all other bullets on contact, you can set up A bullets like this:Code: [Select]task BulletA{
// make the bullet here
ObjShot_SetSpellResist(obj, true);
while(!Obj_IsDeleted(obj)){
DeleteShotInCircle(TYPE_SHOT, TYPE_IMMEDIATE, ObjMove_GetX(obj), ObjMove_GetY(obj), deletion_radius);
yield;
}
}
Check the parameters for DeleteShotInCircle for more information. This deletes bullets that are not spell-resistant, and sets itself as spell-resistant so it doesn't delete itself.
If you're also adding other bullets into the mix that needs some extra work.
let obj = CreateShotA1(ex, ey, 3, randa, DS_BALL_L_YELLOW, 2);
task SetDeleteShotEnable(obj){
ObjShot_SetSpellResist(obj, true);
while(!Obj_IsDeleted(obj)){
DeleteShotInCircle(TYPE_SHOT, TYPE_IMMEDIATE, ObjMove_GetX(obj), ObjMove_GetY(obj), deletion_radius);
yield;
}
}
SetDeleteShotEnable(obj);
KagomeKagome(obj);
If you're interested I could touch it up and post what I have, but you would have to commit to using the API in your scripts; it isn't incredibly intrusive but it would be a change.If it works when running individual singles, I wouldn't mind having a look at least.
If it works when running individual singlesYeah nope ;P
My overlay keeps appearing even when the spell is overThis is insufficient to judge what you're doing. Needs the full script. Currently all I can assume is you're not cleaning up/deleting your objects when the script ends.
My BG script (https://pastebin.com/XkC9wnpu) is here for everyone to see
Good day.
May I, kind of, ask a simple question? Is it possible to earn money by creating own projects on Danmakufu (using my own sprites, music, ect.). In generall, entirely unique project, but just using Danmakufu engine to create it. If no, is there any evidence of that?
Thanks in advance.
So, I want to reveal parts of background only in certain places and shapes, kinda like Doremy's occult attack in AoCF (http://tinypic.com/r/33m9b2d/9), how do I do it? I tried using render targets, but it's too complicated and difficult to use without a tutorial.The only progress I had is that I could change the scale of the mask, but after it reaches the certain point, it just copies itself(something you would see if you put SourceRect of the sprite to 512 when it's original size is 256). So, I would really appreciate the help on this topic, since I don't know anything about HLSL.
Can someone provide me with an example of how to implement History for spell cards? I've been trying to do it with Common data, but I just end up failing, the numbers are always incorrect and don't differ depending on the spell name.
task CutIn(EnemyObject, CutType, CutSpellName, SpellID, CutSpellImage, CutX1, CutY1, CutX2, CutY2){
yield;
let SpellDataAttempt = IntToString(SpellID) ~ GetPlayerID ~ "Attempt"; //name of commondata
let SpellDataGet = IntToString(SpellID) ~ GetPlayerID ~ "Get"; //name of commondata
let SpellValueAttempt = GetAreaCommonData("SpellFunctions", SpellDataAttempt, 0);
let SpellValueGet = GetAreaCommonData("SpellFunctions", SpellDataGet, 0);
//misc code
if(IsReplay == false){
SpellValueAttempt++;
SetAreaCommonData("SpellFunctions", SpellDataAttempt, SpellValueAttempt);
SetAreaCommonData("SpellFunctions", SpellDataGet, SpellValueGet);
SaveCommonDataAreaA1("SpellFunctions");
}
//etc.
}
By using a unique spell ID for each Single, I end up with unique common data names depending on the player, the spell ID, and whether it's attempt or capture.// Spell practise core. Array for the spell cards to track value
// Structure [ state, captureStage, historyStage, capturePrac, historyPrac, scoreBorder, scoreMagic, scoreReimu, scoreYukari, scoreMarisa, scoreAlice ]
// State 0 = unseen/disabled. 1 = Seen. 2 = Captured.
// Number of captures and tries is as they are.
// 01 spell cards
SetAreaCommonData("core","pierre01hard",[0,0,0,0,0,0,0,0,0,0,0]);
@Event {
alternative(GetEventType())
case(EV_USER+9999) {
SetCommonData("spellcardID","pierre01hard");
}
}
pierre01hard is a unique value I have given for this spell card. It basically means "Pierre boss" - "Spell card #01" - "Hard mode"@Event {
case(EV_START_BOSS_SPELL) {
updateCardHistory();
}
case(EV_GAIN_SPELL) {
updateCardCapture();
}
}
task updateCardHistory() {
let spellScriptID = GetCommonData("spellScriptID", 0);
NotifyEvent(spellScriptID, EV_USER+9999, 0);
getResultCard = GetCommonData("spellcardID", "NULL");
let getCommonSpellCardData = [];
getCommonSpellCardData = GetAreaCommonData("core", getResultCard, [0,0,0,0,0,0,0,0,0,0,0]);
// Do stuff with the values and save it back to the AreaCommonData
}
History value is updated when the spell begins and the capture value is updated when the card is obviously captured. It is a bit code-duplication (ugly), but hey it works.And yeah you can't redefine functions. I'm not really sure what's up there; does it happen with all scripts? Does it happen with a fresh DNH copy? Different computer, if you have access to one? There has to be a difference somewhere.
The only progress I had is that I could change the scale of the mask, but after it reaches the certain point, it just copies itself(something you would see if you put SourceRect of the sprite to 512 when it's original size is 256). So, I would really appreciate the help on this topic, since I don't know anything about HLSL.Sorry about that, did forget. Here's a thing I wrote to easily handle stuff like masks, along with an example to showcase.
Also, what are CutIns? Even thought I've heard of them, I don't know what they are.
As for the shaders, now I kinda get how it works, though there are parts that I still don't understand. For instance, the most troublesome part is that the shader cuts off a bit of bottom and right parts of the background, as if it's left top corner was placed at [0,0] coordinates of the screen, and I can't change that at all, is there any way to do so?They are placed at (0,0) firstly because when drawing to a render target, you are literally drawing a new 1024x512 texture so of course the top-left is (0,0), and secondly because past a certain drawing layer the origin is set to (0,0) relative to the window rather than (32,16) like with the STG frame (this applies to everything, it isn't a render target or shader thing).
They are placed at (0,0) firstly because when drawing to a render target, you are literally drawing a new 1024x512 texture so of course the top-left is (0,0), and secondly because past a certain drawing layer the origin is set to (0,0) relative to the window rather than (32,16) like with the STG frame (this applies to everything, it isn't a render target or shader thing).I tried changing scales and positions of litteraly everything, but it still clips, also tried changing the white circle picture a little bit (the circle remains the same size, but there's more black background and it's 512x512), but that didn't affect anything. I may be not noticing something really obvious, so please be patient.
So I'm guessing that the reason it's clipping for you is because you only draw 384x448 on the upper background layer. The bottom one looks sufficiently sized. You could also just move it to (32, 16) but really just make it bigger.
Ooook this is my bad for forgetting to include something.Thanks, that's exactly what I need, now the struggle is finaly over. Also, is there any tutorials on render targets, etc.? I didn't understand some parts of your code, and that may be useful for me in the future.
Like I said earlier, render targets are 1024x512 in size, probably so it's the closest power of 2 to the screen size, which is 640x480. In the HLSL code, by default at the top it declares constants SCREEN_WIDTH and SCREEN_HEIGHT to 640x480. However the reason for this is just because the texture the sample script uses for its mask is 640x480. In fact it's commented "screen size (mask texture size)" in Japanese. So what's happening is that when it gets to the pixel sampling code, it does In.vPos.x/SCREEN_WIDTH to get texture coordinates (which are ratios, from 0 to 1), so e.g. it would try to get texture x-coordinate 1024/640 = 1.6, which isn't valid. It will just clip after it reaches (640,480), and that result is of course squashed, ending up at (640/1024)*640 by (480/512)*480, or 400x450. You can actually notice that your circle isn't actually circular either; this is because the divisions aren't equal ratios: 480/512 > 640/1024.
The solution is simple, just change the constants in the HLSL to 1024 and 512. I also rename them to RENDER_WIDTH/HEIGHT instead for clarity.
let obj1 = ObjPrim_Create(OBJ_SPRITE_2D);
// set up and position obj1
let obj2 = ObjPrim_Create(OBJ_SPRITE_2D);
// set up and position obj2
let obj3 = ObjPrim_Create(OBJ_SPRITE_2D);
// set up and position obj3
CreateRenderTarget("example_texture");
RenderToTextureB1("example_texture", obj1, false); Obj_Delete(obj1);
RenderToTextureB1("example_texture", obj2, false); Obj_Delete(obj2);
RenderToTextureB1("example_texture", obj3, false); Obj_Delete(obj3);
// "example_texture" now has three objects drawn on it, despite the objects being deleted now
let obj4 = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj4, "example_texture"); // use the render target as texture
ObjSprite2D_SetSourceRect(obj4, 0, 0, 256, 256); // for example
ObjSprite2D_SetDestRect(obj4, 0, 0, 256, 256);
ObjRender_SetPosition(obj4, 192, 224);
// spin it
let t = 0;
loop{
ObjRender_SetAngleZ(obj4, t);
t = (t+3) % 360;
}
How do I make the player stop moving in a Sakuya-like timestop?There is no function to disable player control looking at the wiki. Never implemented this myself, but brainstorming here are few things you can try to experiment with:
There is no function to disable player control looking at the wiki. Never implemented this myself, but brainstorming here are few things you can try to experiment with:
- Drop player movement to 0 and restore it post time stop
- Lock and force X Y location of player and release post time stop
How can I fix the cutin, the lifebar and the timer?
// Example th_dnh.def
package.script.main = script/path/to/package.dnh
window.title = some title
screen.width = 640
if(PlayerDying){
dont;
}
That is, interrupt the player's rebirth frames, like if they'd counter-bombed.What are you trying to do, what are you currently doing, and what code are you using?
I'm trying to do the following:I have no idea. It seems like Danmakufu itself just seems to be hard-coded to stop the death process if a bomb is initiated (this can also be done with the CallSpell function). This basically means that forcing the player to bomb upon getting hit is the only way to keep them alive. Fortunately, all the system needs is to recognize that a bomb has been activated. It doesn't have to actually do anything. In order for it to accept it as a valid bomb, I believe you simply need to have to call SetScriptResult(true); in the EV_REQUEST_SPELL block to signal to the system that the bomb has been activated. Following that, I think you just need to call Obj_Delete(GetSpellManageObject); to make sure the bomb ends as soon as it activates so it's doesn't do anything but save you from death. You may need to add some invincibility frames though, just to make sure the player isn't immediately hit again.Code: [Select]if(PlayerDying){
That is, interrupt the player's rebirth frames, like if they'd counter-bombed.
dont;
}
What actually stops the player dying when they counter-bomb?
Also, I'm trying to do something weird where the player controls another thing and the actual player object stays in place. I've got the controlling it part handled, but I'm running into difficulties with giving it a hitbox, since ObjPlayer_AddIntersectionCircleA1 is meant to be set once rather than each frame.It looks like you can use ObjPlayer_AddIntersectionCircleA1 to add any number of player hitboxes, but the location of them seems to be forced to be relative to the player object's location and not independently controllable. You might have to do something hacky to make that work, like make the player's true object location be different from where it appears to be or to manually code an independent hitbox yourself.
If it's relative to the player location you can set it to (-player_x + hitbox_x, -player_y + hitbox_y) for an absolute position, if that's an issue. You can also start with ObjPlayer_ClearIntersection(player) followed by the hitbox additions to set them every frame, even though that's pretty janky.I tried it like this already, but somehow the hitbox just stays on the player. The old one gets cleared and replaced with the new one (based on size), but it's still in the same place.
echo, echo, echo, echo, echo, echo
https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1375135.html#msg1375135
Is there a collection of useful functions in one txt/dnh file?There isn't. You will need to make your own or check out the code snippet thread where people post these. Some have been posted even in this thread.
I swear this is the 5th? 6th? time I've seen it requested lol. Might as well just slap it on the Danmakufu Wiki under tutorials and hope people go there first?Sounds like a good idea. A separate wiki page posting code snippets + a screenshot of the result.
Is there a discord group specific in danmakufu ? since I saw python's video there's a secret santa's scripts so I'm really curious
Does anyone know the bullet cap in danmakufu? Or other caps like sprite/object/enemy etc
There are a few Danmakufu-specific groups (such as the Land of Codes and Apertures) and a number of servers with danmaku channels (such as the main Len'en Discord Server)
There may be a hard bullet cap but if there is, you're probably lagging down to single digit FPS values anyways. There is no limit on graphical objects such as sprites. As for enemies, there can be only one boss enemy on screen at a given time, but you can have any number of standard enemies.
There may be a hard bullet cap but if there is, you're probably lagging down to single digit FPS values anyways. There is no limit on graphical objects such as sprites. As for enemies, there can be only one boss enemy on screen at a given time, but you can have any number of standard enemies.What is a generally accepted bullet limit that works well on low end PCs and is under what most scripts use? 1024?
Ah, I see. Then how can I apply/join the Discord group ?I would like to join it too :D
I would like to join it too :D3 of us !
How can I make multi phased Nonspells and Spells?
and
Can I put two shotsheets in one plural script?
Multi-phased: Have multiple tasks. Not all tasks need to run while the boss is alive either. You can have a task that does one thing for x frames, then does another thing for y frames, etc.Can you give an example, because I can't understand clearly.
Can you give an example, because I can't understand clearly.
task mainTask {
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0) {
//Phase 1
loop(6) {
ascent(i in 0..36) {
ascent(j in 0..4) {
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2 + j/4, GetAngleToPlayer(objBoss) + 360/36*i, 4, 5);
}
}
wait(20);
}
wait(120);
//Phase 2
let randangle = rand(0, 360);
ascent(i in 0..120) {
loop(4) {
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 1 + i/30, randangle, 6, 5);
randangle += 360/4;
}
randangle += 7.1 + i/30;
wait(2);
}
wait(120);
}
}
task mainTask {
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0) {
//Phase 1
taskA;
wait(120); //time for taskA to run
wait(120);
//Phase 2
taskB;
wait(240); //time for taskB to run
wait(120);
}
}
task taskA {
loop(6) {
ascent(i in 0..36) {
ascent(j in 0..4) {
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2 + j/4, GetAngleToPlayer(objBoss) + 360/36*i, 4, 5);
}
}
wait(20);
}
}
task taskB {
let randangle = rand(0, 360);
ascent(i in 0..120) {
loop(4) {
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 1 + i/30, randangle, 6, 5);
randangle += 360/4;
}
randangle += 7.1 + i/30;
wait(2);
}
}
task mainTask {
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0) {
//Phase 1 last until the boss's life gets below 3000
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 3000) {
loop(6) {
ascent(i in 0..36) {
ascent(j in 0..4) {
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 2 + j/4, GetAngleToPlayer(objBoss) + 360/36*i, 4, 5);
}
}
wait(20);
}
}
wait(120);
//Phase 2
//If there were a third phase when the boss got to, say, 1500 health, you'd just put a similar while loop around Phase 2 as well
let randangle = rand(0, 360);
ascent(i in 0..120) {
loop(4) {
CreateShotA1(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 1 + i/30, randangle, 6, 5);
randangle += 360/4;
}
randangle += 7.1 + i/30;
wait(2);
}
wait(120);
}
}
task mainTask {
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0) {
//Phase 1
taskA;
wait(120); //time for taskA to run
wait(120);
//Phase 2
taskB;
wait(240); //time for taskB to run
wait(120);
}
}
Just to note, I already knew about the division by the boss health, I made "First and Nameless Danmaku" with my old Mamizou script (the first) --- but thanks anyways ;)
task mainTask(){
phaseA(3000);
wait(120);
phaseB(0);
wait(120);
}
function phaseA(life_t){
while(check_life(life_t)){
loop(60){
// shoot bullet
if(!wait_check_life(3, life_t)){ return; }
}
if(!wait_check_life(120, life_t)){ return; }
}
}
function phaseB(life_t){
while(check_life(life_t)) {
// do stuff
if(!wait_check_life(120, life_t)){ return; }
// do stuff
if(!wait_check_life(120, life_t)){ return; }
}
}
function check_life(life_t){
return (ObjEnemy_GetInfo(objBoss, INFO_LIFE) > life_t);
}
function wait_check_life(n, life_t){
loop(n){
if(check_life(life_t)){ yield; }
else{ return false; }
}
return true;
}
n = i-whole;
alternative( floor(n/((|n|)+1)) - floor(-n/((|-n|)+1)) ) //sign(n)
case(-1){ x = 5; }
case( 0){ x = pieces; }
case( 1){ x = 0; }
when I could very easily just goif(i<whole){ x = 5; }
else if(i==whole){ x = pieces; }
else { x = 0; }
and long story short I need someone to tell me to stop.How do item scripts work? I haven't been able to find a good resource. More specifically, how do I change the graphics used for items? The defaults are... ugly. ...Where are the default item graphics even stored, for that matter?You can't change the default item handling; they're probably just packaged right into the game. Rather, even if you could change the defaults it wouldn't be a good idea. Defining your own items instead is just the better course of action.
Another question: How big is the potential performance difference between if statements and alternatives in Danmakufu?If this were a compiled language there could be optimizations done with jump tables, depending on the context, the compiler, settings used, etc, but it also just as easily can compile to literally the same thing as if you used if statements. More than that though, this is an interpreted language running on an engine and such specific optimizations can't even be applied, it depends entirely on how the engine handles it. The difference between ifs and switches is extremely negligible, if it's even different at all here, and is greatly overwhelmed by like, everything else. There is no way that branching is going to impact performance in meaningful ways and I would recommend not focusing too hard on it because that is definitely not where your heaviest parts are going to be. I highly anticipate that the extra massaging you do to get the cases you want would end up outweighing any potential benefits, if they even exist.
Random question: Where do I change nicknames on here? I don't see it in forum profile with the rest.Display names are changed in Account Settings. "Nicknames" are intentionally static and can only be changed by admins.
Here's a blurb (+linked blurb) that might be good enough:Thanks! Is there anything on what to put in the item data file? Or just point me at a script that uses it to dig through?
https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1373257.html#msg1373257
#UserItemData
item_image = "./img/item.png"
//Point item
ItemData{
id = 1
rect = (208, 0, 224, 16)
out = (208, 16, 224, 32)
render = ALPHA
alpha = 255
}
//Power item
ItemData{
id = 2
rect = (192, 0, 208, 16)
out = (192, 16, 208, 32)
render = ALPHA
alpha = 255
}
Is there a way to check what kind of object an object is? Like, a task that checks if an object is a laser and does something different if it isn't.
max(3, floor((min(m, n) - 12) / 3))
So it takes the smaller dimension (say n), then for n<21 all hitboxes are radius 3, and n>=21 it increases by 1 every 3 pixels.So I'm trying to implement continues, and the main difficulty I'm having is the part where the game actually... you know... continues. I assume what I need to do is start a script manually, rather than using the end scene script... Something more like how the pause script works?Actually, implementing a continue system is way more complicated than this. First of all, you need to provide us more details about your current setup. What are you currently using? A regular set of scripts in a plural? Stage scripts? Package scripts?
I tried manually loading (both regular and in thread) and starting the end scene script from the main loop of the stage script and waiting for it to finish before deciding whether to close the stage scene, which froze the game. Mucked about with that for a while before concluding that I wasn't going to accomplish much fumbling around with no idea what I'm doing.
collision = (r, x, y) creates a hitbox of radius r positioned (x, y) from the bullet center.
After some testing, the formula for default hitbox radius given a bullet of size m*n isCode: [Select]max(3, floor((min(m, n) - 12) / 3))
So it takes the smaller dimension (say n), then for n<21 all hitboxes are radius 3, and n>=21 it increases by 1 every 3 pixels.
As for the last bit about displaying hitboxes, I made a thing to do this a while back:
https://gist.github.com/drakeirving/c4c12533fd7814d405e1
If you save an image of a white circle (example (https://i.imgur.com/4y349t6.png)) as eff_circle.png and run TDrawHitboxes() in your system script (or I guess anywhere works) you can toggle hitbox visibility by pressing the H key.
Actually, implementing a continue system is way more complicated than this. First of all, you need to provide us more details about your current setup. What are you currently using? A regular set of scripts in a plural? Stage scripts? Package scripts?Oh, boy. Currently I'm up to stage scripts, but I intend to move to a package script at some point soon, since the intent is to make a full game (since I've found myself leading a group project this semester and nobody else had any ideas). If you need more detail, here (https://github.com/JonAjuhan/cs401Project/tree/master/th_dnh_ph3/script/_Dev)'s our github.
Is there a tutorial or handy post about Custom players?It's fairly straightforward for the most part. I recommend starting off by modifying an existing player script - maybe look at several made by different people and pick whichever one whose structure seems the most intuitive to you.
I'm having some ideas for spells and shots that would be cool to have... :wat:
Is there a tutorial or handy post about Custom players?
I'm having some ideas for spells and shots that would be cool to have... :wat:
Are there any tutorials for making shaders? Mainly I want to try to make one that creates the background distortion around the boss, but I don't want to steal someone else's code and trying to make any sense out of the shader scripts is almost impossible without any documentation, since they differ from all the other scripts.
but I don't want to steal someone else's codeThis is typically something not many people will have issue with, especially since I'm sure most people just copied stuff straight from the sample script that does this (SamplePS03_HLSL). The only thing you might even need to change from the sample script is adding color.a = 1; before setting Out.color = color. The main reason you don't see much documentation about shaders in the context of DNH is that most people don't use it for much.
while(TaskA_IsRunning and !TaskB_IsRunning){
shoot_that;
}
while(!TaskA_IsRunning and TaskB_IsRunning){
shoot_this;
}
So my stage scripts are still freezing up for a while when they start a plural, despite loading the plural earlier. I just had the idea to start the plural immediately, and in the plural script load all the singles and then wait for common data or an event before starting them.If this is about script compilation, you should wait both after compiling the plural and starting it from the stage, and waiting after setting up and compiling the boss scene before starting it.
Is this a good idea, or a terrible one?
Translate to danmakufu code plz:Why are you splitting it into tasks if you're only running one at a time?
wait both after compiling the plural and starting it from the stage, and waiting after setting up and compiling the boss scene before starting it.Run that by me again? Not 100% sure I'm parsing that right.
Stage: Load plural; Start plural; other stuff; Notify plural; Wait for plural to close
Plural: Add singles to boss scene; Load boss scene in thread; Wait for event; Register boss scene; Wait for boss scene to end
Which seems to be working pretty well. It still hangs for a few moments, but not nearly as much as before.I still don't think it's a super clean approach.Is there a cleaner approach? How do you deal with it?
Is there any discernible reason things don't load fast enough? If it's resources rather than script compilation doing this might not even fix the issue.I think the bulk of it is script compilation, and the remaining bit is resources. I would go through watching the log to make sure, but my computer just BSOD'd and I need to be getting to bed.
Translate to danmakufu code plz:I'm not sure why you wouldn't just do it in the respective tasks, but:
let numA=0; let numB=0;
task TaskA{
numA++;
do_that;
if(numB==0){ shoot_that; } //the sane way
numA--;
}
task TaskB{
numB++;
do_this;
if(numA==0){ shoot_this; } //the sane way
numB--;
}
task TaskC{
loop{
if(numA>0 && numB==0){ shoot_that; }
else if(numB>0){ shoot_this; }
yield;
}
}
You can't directly check if a task is running like that, so you'd need to keep track of it manually as above.
When you say Load plural -> Start plural, you should have a short time between those to wait for it to compile or it'll block execution (causing the stall) until it's done.Oh, I see. Tried putting it in a task with a wait(600) and it definitely started faster, yeah.
Does anyone know the cause for the get_center_x not defined error when trying to recreate spell cards using Sparens guide?Insufficient information provided to help out. Wild question: Did you create such a function first?
Does anyone know the cause for the get_center_x not defined error when trying to recreate spell cards using Sparens guide?
let count = 0;
loop{
count += 1;
if(GetVirtualKeyState(VK_SHOT) == KEY_PUSH || count >= 60*15){
break;
}
yield;
}
function wait_for_ok(n){
if(n > 0){
loop(n){
if(GetVirtualKeyState(VK_OK) == KEY_PUSH){ break; }
yield;
}
}else{
while(GetVirtualKeyState(VK_OK) != KEY_PUSH){ yield; }
}
}
The part that I remember having the most trouble with was having the dialogue pause until you pressed "Z".Here's a slightly better implementation if some players are still shooting when you advance dialogue:
let count = 0;
while(GetVirtualKeyState(VK_OK)!=KEY_PUSH && count < 60*15){
SetVirtualKeyState(VK_SHOT, KEY_FREE);
yield; count++;
}
VK_OK and VK_SHOT are distinct despite sharing the same key, so you can not only wait for the player to press Z but forcibly prevent the player from shooting, even if the player script doesn't properly respect SetForbidPlayerShot. Might not be necessary, but it's a problem I've had in the past.Is there a tutorial for Dialogue?(Cutin or textbox type)I don't know about a tutorial, but there are various libraries floating around. I got mine from one of Python's scripts (like this one (http://www.bulletforge.org/u/python/p/sumireko-doremy-dream-team-locaa-11-entry)), though I'm not 100% sure whether they wrote it or got it from someone else. The one in the linked script uses a dialogue box, though I've also seen versions of the same library modified to use text bubbles.
It was extra recollection 1, eternal meek. After I add the wait in the code it gives me an error of a bracket missing when there are none missing, but if I add a bracket that's when it gives me a get_center_x not defined error.
let num_options = 9;
ascent(i in 0..num_options){
rendernightmare(i * 360/num_options);
}
Then giving rendernightmare the angle as a parameter instead of making the initial angle random.
So for the movement, the 50 refers to the radius, or distance between the player and the option, while the cos(angle) refers to the displacement in x-position at that angle. Similarly sin(angle) is the displacement in y-position at that angle. (Speaking of this, your cos and sin are swapped, but in this case it doesn't really matter, it's just as though the angle is moved 90 degrees.)
(https://i.imgur.com/qQOeJTq.png)
Given this, if you wanted another option, you would have to set them to a different position around the player, but all you need for that is a different angle (note that the current option moves by change in the angle around the player). So calling another rendernightmare but using angle+something instead would be enough. If you want nine of them, and all evenly spaced, you can divide the 360 degrees into 9 (40 degrees between each). You can do this automatically with an ascent loop:Code: [Select]let num_options = 9;
Then giving rendernightmare the angle as a parameter instead of making the initial angle random.
ascent(i in 0..num_options){
rendernightmare(i * 360/num_options);
}
Whereever you're calling rendernightmare, you would put that blurb instead. You'd then give the task itself an angle parameter, like task rendernightmare(angle), and remove the part in the code where you initialize it as a random angle. If you don't really get how parameters work you should probably go over tutorials.
How can I grow bullets, and their hitbox?
First, put your bullet in a pot of nice, moist soil. Sprinkle water at room temperature on a regular basis. Larger bullets need less water. Remember to keep your pot in a place where sunlight shines frequently, such as near a window. In about three weeks or so, your bullet will have become about three times bigger, and have sprouted a hitbox about a third of its size. It will be harder to tell for irregularly-shaped bullets, but in general, they should reach from the center halfway towards the transparent part of their graphic.
For danmakufu ph3, it is not possible to set more vitual keys for recording in replay, right?
Making one more fake player that can shot and be hit is simple, but the limiting vitual keys is clearly not enough for something, like a double-play stage or so. I hate when I have to cut the replay part when creating such script. :wat:
Please refer to https://dmf.shrinemaiden.org/wiki/Input_Functions
let VK_SHOT_P2 = VK_USER_ID_PLAYER + VK_SHOT;
AddVirtualKey(VK_SHOT_P2, KEY_Y, KEY_INVALID);
By "randomly" do you mean actually randomly, intermittently, or suddenly stopping altogether? What does the log window say about the shot count? Do spawning effects still occur? Have you confirmed this with other player scripts, even though that is likely not the issue?
I don't have any spawning effects for my script, but bullets that don't spawn are actually randomly not spawning (like 2-4 bullets in a ring not necessarily in a row) and they're not just invisible since there's no hitbox where they should be. I tried other shots and they don't appear to cause this...
Can you provide some code snippets and more details about your coding environment, libraries, etc? Are you using multiple shot sheets?https://www.dropbox.com/s/4kyjx2fxxqy87hf/_generic%20junko.zip?dl=0
https://www.dropbox.com/s/4kyjx2fxxqy87hf/_generic%20junko.zip?dl=0
Unable to replicate your issue. My best guess is that your computer's hardware is not capable of handling over 8000 ADD rendered bullets at once and something went wrong with Danmakufu.
Given that I've only been experiencing this issue (not just with this script btw) with Ultima's DDC ReimuB I'll pin the blame on that, and just use another player then. Thanks for the help.
Given that I've only been experiencing this issue (not just with this script btw) with Ultima's DDC ReimuB I'll pin the blame on that, and just use another player then. Thanks for the help.maybe you should not try throwing 8000 bullets on the screen regardless
maybe you should not try throwing 8000 bullets on the screen regardless
Here are some concerns I found:
- In spell4.dnh, CheckHitWall will return null if the bullet is deleted somehow, leading to angle being unset when you use it, throwing an error. You might not have seen this error but it happened on my first run.
- In functions.txt, for PlaySound you do something like if(str == "Shot1"){ObjSound_Load(s,MainSTG~"sound/Shot1.wav");} but like 30 times, which means:
- You aren't using else-ifs so as to not compare against every string
- You aren't using alternative-case which is what you should be doing instead, given you want to choose between all these string comparisons
- Note that you can replace all this boilerplate with ObjSound_Load(s,MainSTG~"sound/"~str~".wav"); given that all the strings being called are also the filenames
- You don't delete the sound objects after you create them, but you create a new object for every call, so you'll have a gazillion of them quickly.
This last one will cause your issue, as the number of objects will grow endlessly and start causing memory leaks or whatever else. If you're using sounds in your original script, which is what I suspect, this is almost surely the cause.
If this is the case, I would guess that the reason you see it with that particular player script could be that with other player scripts you end the fight sooner and don't have enough time for the problem to build to critical levels.
The final script'll just use another Reimu shot that doesn't have the issues but kills everything at roughly the same time.That... doesn't solve the issue though. You're claiming that it's the player script, but even if Ultima's script has some minor problems with resource usage it shouldn't be as significant as throwing so many bullets on screen. If it is a problem with Ultima's script, then it would be good to find out what the problem is and get it fixed, not just ignore it. I've also spent a good deal of time going through both of your scripts, so I would like some closure here. Can you replicate the problem while giving more information? If you replicate the bug but have the log window open (as Hele just posted how to do) and post screenshots that could help tremendously in pinpointing the issue.
Edit: It just occured to me that I did modify Ultima's player script slightly in changing the grazebox, so I've uploaded my modified player script and a replay with the issue (at least on my PC).
https://www.dropbox.com/s/kq824xvw9f6pvfm/package2.zip?dl=0
...This is the dnh folder I was using...This makes absolutely no sense. Why did you upload your entire dnh folder but then removed the player script and now are separately uploading it because you thought you modified the player script? You were suppose to upload your entire Dnh folder without cleaning up anything. I explicitly requested this.
...Edit: It just occured to me that I did modify Ultima's player script slightly in changing the grazebox,..
This makes absolutely no sense. Why did you uploaded your entire dnh folder but then removed the player script and now are separately uploading it because you thought you modified the player script? You were suppose to upload your entire Dnh folder without cleaning up anything. I explicitly requested this.
That folder I uploaded was the one I released for the external contest. Sorry about that, I was trying to minimize the download size since I had a lot of other scripts.This dnh folder does not function. Booting it spits out this massive 1.45mb log. Here is a snip: https://pastebin.com/6584Dk5u
https://www.dropbox.com/s/d3phs0k07ut79py/danmakufu%20ph3%20pre6a.zip?dl=0
This dnh folder does not function. Booting it spits out this massive 1.45mb log. Here is a snip: https://pastebin.com/6584Dk5u
Once loaded, I am missing all player scripts except Reimu MoF.
I know that 0.12m is a old version, but I really want to try to make something...As moderator I need to alert you of the following: It is not encouraged to make anything in 0.12m. I've written in the FAQ about this. The only things that should be supported is getting old scripts to work for research/playing purposes. Seeing that you aren't trying to get someone else's script to work but actually attempting a creation I suggest to do it in ph3.
The problem is: Danmakufu keeps crashing without the menu(with AppLocale and LocaleEmulator),
when I open naturally it opens the menu, but when I select ExRumia (directory) *crash*
Plz Help mee
I do have another issue though. In all variants of spell5, occasionally, the second phase with the green bullets won't trigger and nothing spawns except for the red wall. I tried cleaning up the script and make the health a global variable, then have mainloop update it every frame, but it still fails to trigger sometimes. Is there someone wrong I'm doing with the conditionals?Can't replicate after like 10 attempts. Have a replay? Preferably of just the spell?
Can't replicate after like 10 attempts. Have a replay? Preferably of just the spell?
function a{
b;
}
task b{
loop(10){
c;
yield;
}
break;
}
function c{
break;
}
In the above example: a calls b; b starts a loop and calls c; c breaks, cascades back to b, and breaks the loop; b then breaks after the loop, cascades back to a, breaks a, then keeps cascading break to whatever a's context was.Always use return to end a function or task. I suggest fixing anywhere in your code that breaks instead of returning.I suddenly have a sense of deja vu...
let size=10; arr=Arr_Init(size,0);
let ops_per_frame = 10000;
loop{
loop(ops_per_frame){
let v = Arr_Get(arr,i);
Arr_Set(arr,i,v+1);
i=(i+1)%size;
}
yield;
}
With the methods using an alternative on a global to determine which type of "array" to use. (Here's the code (https://pastebin.com/qwRGdDyg) for the methods.)V: | 27 | | 33 single variable (ignoring index)
v: 13 | | 13 | 12 10 variables w/alternative
n: 09 | 24 | 21 | 19 normal array
o: 14 | 16 | 16 | 15 object dictionary
c: 09 | 11 | 10 | 10 common data
a: 09 | 11 | 11 | 10 area common data
It seems like none of them are faster than normal arrays, aside from in the first set of tests. It also seems that the alternatives for working with the individual variables are actually slower than just using an arrays.So I was wondering how people get the boss's health bar to be a red circle around the boss instead of on the top of the screen. To add to this, could anyone help me with spellcard pictures? Like whenever a spellcard is declared, usually a picture of the boss hovers over the screen for a second. How do I do this?The hovering of the boss and such is called often a ' cutin '. It is nothing else than drawing a texture on the screen and then moving it around in a sequence. You can code it yourself or download ready made scripts. Have you checked the sticky Information thread (https://www.shrinemaiden.org/forum/index.php/topic,6181.0.html)?
The hovering of the boss and such is called often a ' cutin '. It is nothing else than drawing a texture on the screen and then moving it around in a sequence. You can code it yourself or download ready made scripts. Have you checked the sticky Information thread (https://www.shrinemaiden.org/forum/index.php/topic,6181.0.html)?Thank you, this will help a lot! While I'm here could I ask if there are any ready made scripts to make dialogue? If not, what is an easy way to create a dialogue function/system?
The circular life bar I am unsure whether it was mentioned here or not. Need some extra reply on this one.
Thank you, this will help a lot! While I'm here could I ask if there are any ready made scripts to make dialogue? If not, what is an easy way to create a dialogue function/system?There are various libraries floating around. Here (http://www.bulletforge.org/u/python/p/sumireko-doremy-dream-team-locaa-11-entry)'s one of Python's scripts using one.
There are various libraries floating around. Here (http://www.bulletforge.org/u/python/p/sumireko-doremy-dream-team-locaa-11-entry)'s one of Python's scripts using one.Sorry I'm not that experienced, but I found the Dialogue file but I can't seem to find him using it anywhere in the game. How would I use this file with it's functions?
Sorry I'm not that experienced, but I found the Dialogue file but I can't seem to find him using it anywhere in the game. How would I use this file with it's functions?Something like this (https://pastebin.com/teNkfkvX), usually in a separate single. (Ignore SetBGM and ShowEnemyTitle, those aren't part of the library.)
how people get the boss's health bar to be a red circle around the boss instead of on the top of the screenHere (https://pastebin.com/ptXVX62h)'s a task I grabbed from somewhere to do it. (You'll probably need to change the filepaths.)
Something like this (https://pastebin.com/teNkfkvX), usually in a separate single. (Ignore SetBGM and ShowEnemyTitle, those aren't part of the library.)Thank you so much!
Here (https://pastebin.com/ptXVX62h)'s a task I grabbed from somewhere to do it. (You'll probably need to change the filepaths.)
Something like this (https://pastebin.com/teNkfkvX), usually in a separate single. (Ignore SetBGM and ShowEnemyTitle, those aren't part of the library.)Sorry, just one more question. Every time I try to use the Dialogue pastebin you gave me, the entire program crashes. (yes I changed the images to my own)
Here (https://pastebin.com/ptXVX62h)'s a task I grabbed from somewhere to do it. (You'll probably need to change the filepaths.)
Sorry, just one more question. Every time I try to use the Dialogue pastebin you gave me, the entire program crashes. (yes I changed the images to my own)Could you copy-paste the error messages you get, or does your program freeze and not respond?
Could you copy-paste the error messages you get, or does your program freeze and not respond?It freezes and doesn't respond
Magikrow, I am suspecting that you're very new to Danmakufu in general and you're already attempting to use someone else's code without actually understanding what you're doing. Dialogues and circular lifebars are intermediate to expert level scripting effects. Unless they are really dummy-proof prepared and offered, you're not going to get it right.Yes I am very new, however I did get the circular lifebar to work. Dialogue really seems to be the only thing I've had a big struggle with working with danmakufu. Is there somewhere I can learn more about it?
That dialogue code paste is never going to work because it is incomplete. It is an example, not a ready to use script. The initial dialogue you got is a playable script from Python's. The author probably integrated the dialogue functionality it into its own work. He/she already understands how to work it out.
So, I know Danmakufu is kinda bad about arrays. What I'm not sure of is the relative speed of common data and object dictionaries. My guess is it's at least somewhat slower than just using a variable, but I'm unsure how it compares to arrays.Warning, incoming wall
function array(size, value){
let a = [value];
while(length(a) < size * 2){
a = a ~ a;
}
return a[0..size];
}
let a = "a";
Obj_SetValue(a, "key", "a:val");
let b = "b";
Obj_SetValue(b, "key", "b:val");
Obj_GetValueD(a, "key", "a:null"); // => "b:val"
Obj_GetValueD(b, "key", "b:null"); // => "b:val"
Obj_GetValueD(0, "key", "0:null"); // => "b:val"
How do you get info of a bullet ID such as delay color from within the script?You can use the GetShotDataInfoA1 (https://dmf.shrinemaiden.org/wiki/Shot_Functions#GetShotDataInfoA1) function. It needs the shot graphic id that you want to look up, and the type of information you're looking for. In your case that would be INFO_DELAY_COLOR.
There are still some lingering misconceptions about this because back in 0.12m arrays were not O(1) access.So THAT's why I was thinking they were slow. I must have heard that somewhere and not realized it was outdated.
Now for some problems with your tests.Yeah... Well, they weren't really intended to be exhaustive, just trying to get a general idea, but you're right, it was pretty slapdash.
AddScore() has less overhead than incrementing a variable, so I use this. It's the operation with the least overhead I bothered testing that demonstrably does something.Huh. How does that work? I would have thought it would still just be incrementing a variable.
Huh. How does that work? I would have thought it would still just be incrementing a variable.
So the distortion effect in SampleE02, is there a way to do that with a shader instead of breaking the image up into a spritelist? ...Preferably with working example because I'm still just beginning to fumble my way through figuring out HLSL.What part of it? If it's just the distortion, then SamplePS03 already does mostly that. The darkness thing also wouldn't be too difficult, it would just require modifying the pixel colors to be the regular color minus a function of distance from the center, which SamplePS03 already uses.
If it's just the distortion, then SamplePS03 already does mostly that.Whoops, I remembered there was something to do that in the samples and stopped checking when I found one in E02. Never mind!
2018/04/21 18:37:37.842 読み込み完了待機(ScriptManager):
(something like "waiting to finish reading") every few seconds.How can I make multiphased nos and spells? Like Reimu in CtCI know I've already asked this but I didnt understand it, and also lost he post... :blush:
function Notify(type,event,args){
let id = GetScriptID(type);
if(id==ID_INVALID || type==SCRIPT_ALL || ((type==SCRIPT_PACKAGE)!=(GetOwnScriptID==GetScriptID(SCRIPT_PACKAGE))) ) {
NotifyEventAll(event,args);
}
else{
NotifyEvent(id,event,args);
return GetScriptResult(id);
}
}
Currently, it does not work. Specifically, it doesn't return anything, and I get a "trying to use a variable that has not been set" when I try to use the result.NotifyEvent(GetOwnScriptID,EV_REQUEST_IS_DURABLE_SPELL,[]);
let foo = GetScriptResult(GetOwnScriptID);
WriteLog(foo); //errors
Yielding between notifying the event and getting the result didn't help. I also tried notifying a different script (I added a case to my system script to test) with the same result.task SpellCast(Text){
let slideX = GetScreenWidth;
let slideY = 0;
let slidetxtX = 0;
let slidetxtY = GetScreenHeight/2;
let SpAnFr = 0;
let Alpha = 0;
let ZAngle = 0;
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
let txtobj = ObjText_Create();
//==========================================
ObjText_SetFontBorderType(txtobj,BORDER_FULL);
ObjText_SetFontSize(txtobj,10);
Obj_SetRenderPriority(txtobj,1);
ObjRender_SetX(txtobj,slidetxtX);
ObjRender_SetY(txtobj,slidetxtY);
ObjText_SetFontColorTop(txtobj,0,255,0);
ObjText_SetFontColorBottom(txtobj,0,255,0);
ObjText_SetFontBorderColor(txtobj,1,100,1);
ObjText_SetHorizontalAlignment(txtobj,ALIGNMENT_CENTER);
ObjText_SetSyntacticAnalysis(txtobj,true);
ObjText_SetAutoTransCenter(txtobj,true);
ObjText_SetFontBorderWidth(txtobj,2);
ObjText_SetText(txtobj,Text);
//============================================
ObjPrim_SetTexture(obj,imgSpell1);
ObjSprite2D_SetSourceRect(obj,0,0,1000,1000);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetBlendType(obj,BLEND_ALPHA);
ObjRender_SetAlpha(obj,Alpha);
ObjSprite2D_SetDestRect(obj, -500, -500, 500, 500);
ObjRender_SetScaleXYZ(obj,0.5,0.5,0);
ObjRender_SetAngleXYZ(obj,0,0,ZAngle);
Obj_SetRenderPriority(obj,0.95);
ObjRender_SetX(obj,slideX);
ObjRender_SetY(obj,slideY);
while(!Obj_IsDeleted(txtobj)){
ObjRender_SetX(obj,slideX);
ObjRender_SetY(obj,slideY);
ObjRender_SetX(txtobj,slidetxtX);
ObjRender_SetY(txtobj,slidetxtY);
ObjRender_SetAlpha(obj,Alpha);
ObjRender_SetAngleXYZ(obj,0,0,ZAngle);
if(SpAnFr<30){
slideX-=10;
slideY+=8;
slidetxtX+=(GetScreenWidth/2)/30;
Alpha+=255/30;
ZAngle-=(360/30);
}
if(SpAnFr>30&&SpAnFr<120){
slidetxtX+=0.1;
ZAngle-=0.2;
slideX-=0.1;
slideY+=0.1;
}
if(SpAnFr>120){
slidetxtX+=((GetScreenWidth/2)/30)-30;
slidetxtY-=((GetScreenHeight/2)/30)-30;
slideX-=10;
slideY+=8;
Alpha-=255/30;
ZAngle-=(360/30);
}
if(SpAnFr>300){
Obj_Delete(obj);
}
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){Obj_Delete(txtobj);}
SpAnFr++;
yield;
}
}
The Image works fine, but the text doesn't even appear.In order to use a horizontal alignment other than ALIGNMENT_LEFT, you need to use ObjText_SetMaxWidth first. Otherwise it doesn't know where the right boundary is, so how can it center it between the left and right boundaries?
#include "./Library/Cutin.txt"
#include "./Library/Resources.txt" //et
#include "./Library/Functions.txt" // cetera
Other_Script.dnh:#include "./Index.txt"
This way you can change what you're #including all in one place and you don't have to clutter up your scripts with a dozen #includes each.
2. how to make life and spell pieceSo there are a few different parts to that:
3. How to scale up the "out" of a itemI think you'd have to scale it up in the actual image.
I have just a simple question. How would you make danmaku with a zig-zaggy pattern?Depends what you mean by "zig-zaggy". If you mean zig-zaggy like, say, Nue's snakes, you could do something like:
let dir = 1;
while(!Obj_IsDeleted(shot)){
ObjMove_SetAngularVelocity(shot,0.1*dir);
//or ObjMove_SetAngle(shot,a0+45*dir);
wait(30); dir*=-1;
}
@Andi Thank you! I'll keep that code in note but I meant danmaku that changes directions (like from left to right) continuously. An example would be something like this:
https://i.ytimg.com/vi/oJZPZ6gETbQ/maxresdefault.jpg
task example{
let Frame=0;
let y=12;
loop(){
Set_ObjY(obj,y);
y+=sin(Frame);
Frame++;
wait(1);
}
}
This doesn't reflect any existing functions in danmakufu and is just an example of using sin or cos to move an object up and down or left to right smoothly and repetitively.task shoot{
let Frame=0;
let a=12;
while(!Obj_IsDeleted(obj)){
Set_Angle(obj,a);
if(Frame<60){a+=1;} //adding angle addition for current bullet
if(Frame>60&&Frame<120){a-=1;} //switching angle addition for current bullet
if(Frame>120){Frame=0;} //Resetting frame count
Frame++;
yield;
}
}
@Andi Thank you! I'll keep that code in note but I meant danmaku that changes directions (like from left to right) continuously. An example would be something like this:That pattern from Shuusou Gyoku doesn't have bullets that change direction, it's the firing angle that changes direction, and the bullets themselves just go straight but decelerate. If you can fire bullets with the angle increasing, you can do the same while decreasing it instead, and alternate between them for the intended effect. Here's an implementation of this, but note I took a shortcut for increasing/decreasing the angle.
https://i.ytimg.com/vi/oJZPZ6gETbQ/maxresdefault.jpg
let num_waves = 4;
let num_lines = 11;
let min = 0;
let max = 30;
let inc = 3;
let shots_per_wave = (max-min) / inc;
let z = min;
loop(num_waves){
loop(shots_per_wave){
ascent(i in 0..num_lines){
CreateShotA2(192, 200, 4, (i*360/num_lines) + z, -0.1, 1.5, SHOT_RING_RED, 0);
}
z += inc;
if(z <= min || z >= max){ inc *= -1; }
loop(6){yield;}
}
}
Actually, I've got another one as well. When you set the render scale of a shot, that doesn't change its hitbox, right? How do you change its hitbox when you scale it?Would have to do it manually. You can use ObjShot_GetImageID to get the shot graphic ID, GetShotDataInfoA1 to get the collision, and ObjShot_SetIntersectionCircleA1 (or A2 if necessary) to set the hitbox each frame. If you wanted to you could neatly package that all up into its own function like ObjShot_SetScale but I'm too lazy to do it right now.
GetScriptResultThe first trap is that you expect GetScriptResult to obtain the value that you've set with SetScriptResult as though it were returning from a function. If you're unaware of how the event scheduler works, when you trigger an event, it doesn't just run the script's event loop at that moment. (Note, the following is my interpretation) Instead, notifying an event adds the relevant information to a large queue of all events. On a given frame, a global event scheduler (I'm assuming it's global) takes the whole queue of events being triggered and messages the event data to the relevant scripts, and on that frame, that script's @Event routine will be run once for every new event put in that script's event queue. (That or there's another mechanism for scripts to add events to all other scripts' event queues somehow. Or, all events are done together outside of the individual script flow, but I doubt that.)
So there are a few different parts to that:Thanks Andi! You've helped me a lot with this post.I think you'd have to scale it up in the actual image.
- Making the actual item that will add a life/spell piece. Probably the easiest part, it sounds like you've got that covered already based on your (3).
- Making life/spell pieces actually function (add a life/spell after collecting enough). This is also relatively easy. There are a few approaches; I just add a fraction of a life/bomb (and multiply/round/divide by the number of pieces per life/spell to avoid floating point errors) and check if the integer part increased to decide which sound effect to play. Others use common data instead of the actual life/spell count.
- Display life/spell pieces nicely. This is probably the hardest part if you haven't already set up your system script to display lives/bombs as sprites instead of numbers. If you have, it's a matter of displaying a different sprite for the fractional part. Here (https://pastebin.com/i4PnD012)'s the code I use to do it; your Default_System.png won't have the images I'm using so you'll need to mess with that.
case(EV_GET_ITEM){
if(GetEventArgument(0)==ITEM_LIFE_B_P){//life piece
SetPlayerLife(GetPlayerLife+1);
}
}
I don't really get much information from that snippet, especially when items have several places with relevant code. How have you defined the item type? Are you using an item script or just CreateItemU1?I'm using CreateItemU1 in a task (to make that the item spawns like the newer games and does a y-angle spin).
You should test things in order:
1) Does the item appear
2) Does EV_GET_ITEM trigger
3) What is the item ID and what is ITEM_LIFE_B_P
I imagine the problem is at step 2?
See https://www.shrinemaiden.org/forum/index.php/topic,16584.msg1108259.html#msg1108259I've read your tutorials, and merged both the Item Task and Item Const in a single script, and made some code to apply my tasks and item collection with events, as seen here (https://pastebin.com/FMktY3E7), but my item graphics are not appearing (but the "out" is).
Also https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1373257.html#msg1373257
This is why I asked if you were using an item script, and why I figured tests would fail at EV_GET_ITEM. What you have isn't an actual item script, it's an include with a bunch of tasks. In order to have user-defined items work properly you need to write an item script for them, rather than try to define the item behaviour in a player script.
If you really needed some player-specific behaviour on top of the regular item behaviour you could trigger extra events from the item script and handle that event in the player script, or manipulate ObjVals on the player object, or otherwise make fake items. But that doesn't seem to be the case here.
if you use NotifyEvent somewhere, there is nothing to come back from GetScriptResult, as no events have actually been handled yet.I guessed at these issues, but yielding didn't seem to help so I put the first off (but still kept using yields when testing) and figured I'd deal with the second when I managed to get anything back at all.
...
wouldn't two SetScriptResult calls overwrite each other?
That being said, as far as events go it doesn't even matter, because using SetScriptResult in @Event will not affect the value of GetScriptResult outside of @Event! I don't really know why, because script results do persist over time, but that's how it is. In other words, the second trap is expecting that SetScriptResult does anything useful for user events at all.Oh. ...I do so love Danmakufu.
function Notify(type,event,args){
let id = GetScriptID(type);
let hash = GetNextHash(); //nothing fancy atm, just increments and returns an int
args = args ~ [ hash ];
if(id==ID_INVALID || type==SCRIPT_ALL || ((type==SCRIPT_PACKAGE)!=(GetOwnScriptID==GetScriptID(SCRIPT_PACKAGE))) ) {
NotifyEventAll(event,args);
}
else{
NotifyEvent(id,event,args);
}
return hash;
}
function SetEventResult(hash,result){
SetCommonData("EventResult"~itoa(hash), result);
yield; yield;
DeleteCommonData("EventResult"~itoa(hash));
}
function GetEventResult(hash){
let result = GetCommonData("EventResult"~itoa(hash), NULL);
DeleteCommonData("EventResult"~itoa(hash));
return result;
}
task SomeTask{
let evhash = Notify(SCRIPT_ITEM, EV_SPAWN_ITEM, [ I_EXTEND, ex,ey, ex,ey-30 ];
yield;
let item = GetEventResult(evhash);
ObjRender_SetAngleZ(item,180);
}
That seems to work.I've read your tutorials, and merged both the Item Task and Item Const in a single script, and made some code to apply my tasks and item collection with events, as seen here (https://pastebin.com/FMktY3E7), but my item graphics are not appearing (but the "out" is).Discovered the bug, but I can't fix it.
let obj = CreateItemU1(things);
How can I fix it?
How can I make bullet trails?I've seen a example of the kind of code that you want here (https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1295356.html#msg1295356).
Oh, random question. How the heck do I put a backslash in a char? '\' escapes the close ', '\\' throws an exception for being too long to go in a char, and let temp="\\"; temp[0] throws an exception as well.
"\\ "[0]
?Discovered the bug, but I can't fix it.
It happens when I set the item as a variable like:Code: [Select]let obj = CreateItemU1(things);
How can I fix it?
ObjRender_SetScaleXYZ(obj,0.1,0.1,0)
You set the z-scale for everything to 0 which like any other dimension makes it 0 length. It should be 1.task SpawnItem(type,x,y,score,delay){
loop(delay){yield;}
let h1 = 0;
let obj = CreateItemU1(type,x,y,score);
let objRZAngle = ObjRender_GetAngleZ(obj);
let objRYAngle = ObjRender_GetAngleY(obj);
let objRXAngle = ObjRender_GetAngleX(obj);
ObjRender_SetScaleXYZ(obj,0.1,0.1,1);
ascent(i in 0..60){
ObjRender_SetAngleZ(obj,objRZAngle+i*720/60+12);
ObjRender_SetScaleXYZ(obj,(1.7/30)*i/2,(1.7/30)*i/2,1);
yield;
}
loop{
yield;
ObjRender_SetAngleY(obj,objRYAngle+h1*6);
h1++;
}
}
// and then optionally
function SpawnLife(x,y,score,delay){
SpawnItem(ITEM_LIFE_B,x,y,score,delay);
}
function SpawnSpell(x,y,score,delay){
SpawnItem(ITEM_SPELL_B,x,y,score,delay);
}
// etc
The bug was still in action when I do the let obj = CreateItemU1 OUTSIDE of the task, and when I change the Z-scale to 1, the outside of the stage(the frame) is turned to black.Code: [Select]ObjRender_SetScaleXYZ(obj,0.1,0.1,0)
You set the z-scale for everything to 0 which like any other dimension makes it 0 length. It should be 1.
It only "bugs" when you assign the ID to a variable because otherwise the function doesn't act on it, of course.
Also you have a heck of a lot of code duplication. You could very easily make it a lot more compact withCode: [Select]code
and when I change the Z-scale to 1, the outside of the stage(the frame) is turned to black.wat
watHere (http://www.mediafire.com/file/dyles51lbo37y6x/Tenshi_Hinanawi_Boss_Fight_by_Zino.rar)
Can you just upload your folder or something, this is too strange for me to speculate about.
CreateShotA1(BossX, BossY, 2, AimPlayer(), DS_BALL_S_RED, 10);
shot_id = return;
let shot_id = CreateShotA1(BossX, BossY, 2, AimPlayer(), DS_BALL_S_RED, 10);
I guess I thought that using return; would be the value of the last thing a function returned.You can make a task that plays a descent loop, and make that the bullet have a angular velocity, then wait, then have the same angular velocity, but negative.
My next question is that how you can make a bullet fly in a wavy motion? I know I need to use ObjMove_SetAngularVelocity(id, r);. I was hoping to make it so that the wavy motion started small and as the bullet travels further, the it would start waving further to each side.
task Waving(obj){
descent(i in 0..100){//a really big number to make things to not stop waving(number of times the bullet will wave)
ObjMove_SetAngularVelocity(obj,i/10);
loop(180/(i/10)){yield;}
ObjMove_SetAngularVelocity(obj,i/-10);
loop(180/(i/10)){yield;}
}
}
I guess I thought that using return; would be the value of the last thing a function returned.
My next question is that how you can make a bullet fly in a wavy motion? I know I need to use ObjMove_SetAngularVelocity(id, r);. I was hoping to make it so that the wavy motion started small and as the bullet travels further, the it would start waving further to each side.
How would I add a sprite for a boss that is in a sprite sheet?
let TDRAWSTATE_IDLE = 0;
let TDRAWSTATE_LEFT = 1;
let TDRAWSTATE_RGHT = 2;
task TDrawLoop(path){
let animframe = 1;
let movestate = TDRAWSTATE_IDLE;
ObjPrim_SetTexture(objBoss, path);
ObjRender_SetScaleXYZ(objBoss, 1, 1, 1);
let bossAngle = ObjMove_GetAngle(objBoss);
let bossSpeed = ObjMove_GetSpeed(objBoss);
ObjSprite2D_SetSourceRect(objBoss, 0, 0, 128, 128);
ObjSprite2D_SetDestCenter(objBoss);
while(!Obj_IsDeleted(objBoss)){
bossAngle = ObjMove_GetAngle(objBoss) % 360;
bossSpeed = ObjMove_GetSpeed(objBoss);
if(bossSpeed > 0){ //below three cases require if statement to prevent reset of animframe.
if((bossAngle > 270 || bossAngle < 90) && movestate != TDRAWSTATE_RGHT){
movestate = TDRAWSTATE_RGHT;
animframe = 0;
}else if((bossAngle > 90 && bossAngle < 270) && movestate != TDRAWSTATE_LEFT){
movestate = TDRAWSTATE_LEFT;
animframe = 0;
}else if((bossAngle == 90 || bossAngle == 270) && movestate != TDRAWSTATE_IDLE){
movestate = TDRAWSTATE_IDLE;
animframe = 0;
}
}else if(movestate != TDRAWSTATE_IDLE){ //if transitioning back to idle (speed = 0)
movestate = TDRAWSTATE_IDLE;
animframe = 0;
}
ObjSprite2D_SetSourceRect(objBoss, 0+floor(animframe/9)*128, 0 + 128*movestate, 128 + floor(animframe/9)*128, 128 + 128*movestate);
animframe++;
if(animframe >= 36){
if(movestate == TDRAWSTATE_IDLE){ //animframe reset for idle
animframe = 0;
}else{ //keep in current position if moving.
animframe = 35;
}
}
yield;
}
}
Yes that was exactly what i needed, thank you. This is going to sound like a dumb question ,but are the (path) parts referring to the path to the image or the TDRAWSTATES?To the path to image.
Do the bullets go through the enemy or stop at it?They stop.
Here (http://www.mediafire.com/file/dyles51lbo37y6x/Tenshi_Hinanawi_Boss_Fight_by_Zino.rar)First, you write let obj = 0; and then proceed to manipulate obj. 0 is the ID of an object; it isn't just nothing! Use -1 if you want to use a dummy value for referencing objects. This is why you're getting the bad STG frame.
task SpawnItem(type, x, y, score, delay){
loop(delay){yield;}
let obj = CreateItemU1(type, x, y, score);
ascent(i in 0..60){
ObjRender_SetAngleZ(obj, 2*(720/60)*i);
ObjRender_SetScaleXYZ(obj, 0.1+(0.9/60)*i, 0.1+(0.9/60)*i, 1);
yield;
}
ObjRender_SetAngleZ(obj, 0);
ObjRender_SetScaleXYZ(obj, 1, 1, 1);
let h1 = 0;
while(!Obj_IsDeleted(obj)){
ObjRender_SetAngleY(obj, h1*6);
h1++;
yield;
}
}
function SpawnLife(x, y, score, delay){
SpawnItem(ITEM_LIFE_B, x, y, score, delay);
}
function SpawnLifePiece(x, y, score, delay){
SpawnItem(ITEM_LIFE_B_P, x, y, score, delay);
}
function SpawnSpell(x, y, score, delay){
SpawnItem(ITEM_SPELL_B, x, y, score, delay);
}
function SpawnSpellPiece(x, y, score, delay){
SpawnItem(ITEM_SPELL_B_P, x, y, score, delay);
}
You could then also trim your event cases withcase(EV_USER+1000){ // Spawn Item event
let args = GetEventArgument(0);
SpawnItem(args[0], args[1], args[2], args[3], args[4]); // type, x, y, score, delay
}
And I have one more problem.The delete-when-0-life task just checks once and then immediately ends. Should be
I have a function that spawns a enemy object like a bullet, and I can set the life, the angle, etc. like a bullet.
But when I set the life and shoot it, the life seems do not go down.
Here[url] is the link to the functions.
(https://pastebin.com/KXQ9djEq)
task DeleteEnemyWhenLife0(obj){
while(ObjEnemy_GetInfo(obj,INFO_LIFE) > 0){ yield; }
Obj_Delete(obj);
}
You can make a task that plays a descent loop, and make that the bullet have a angular velocity, then wait, then have the same angular velocity, but negative.
You can increase the "waving" motion with the descent loop variable, like this:Code: [Select]task Waving(obj){
descent(i in 0..100){//a really big number to make things to not stop waving(number of times the bullet will wave)
ObjMove_SetAngularVelocity(obj,i/10);
loop(180/(i/10)){yield;}
ObjMove_SetAngularVelocity(obj,i/-10);
loop(180/(i/10)){yield;}
}
}
Still having problems with multi phased nonspells/spells, it doesn't work....
Here (https://pastebin.com/aXKkAnjh) is a part of my script
I see literally nothing in that script that compares boss health against a constant except for preventing 0,0 spawning...I don't get it, what should I do?
First, you write let obj = 0; and then proceed to manipulate obj. 0 is the ID of an object; it isn't just nothing! Use -1 if you want to use a dummy value for referencing objects. This is why you're getting the bad STG frame.Oh, now I understand, and I don't get why your SpawnLife/Spell is a function. Can't it be a task?
Second, the reason your stuff wouldn't work properly once you put the item object in the variable is because you have no MainLoop in the item script and therefore no yield in your MainLoop, so none of your tasks will progress.
Third, as a precaution using loop is bad here because there is no way to exit and so the tasks will live as long as the script does.
Here is a small rewrite, including the suggestion I made earlier (add a yielded MainLoop):Code: [Select]task SpawnItem(type, x, y, score, delay){
You could then also trim your event cases with
loop(delay){yield;}
let obj = CreateItemU1(type, x, y, score);
ascent(i in 0..60){
ObjRender_SetAngleZ(obj, 2*(720/60)*i);
ObjRender_SetScaleXYZ(obj, 0.1+(0.9/60)*i, 0.1+(0.9/60)*i, 1);
yield;
}
ObjRender_SetAngleZ(obj, 0);
ObjRender_SetScaleXYZ(obj, 1, 1, 1);
let h1 = 0;
while(!Obj_IsDeleted(obj)){
ObjRender_SetAngleY(obj, h1*6);
h1++;
yield;
}
}
function SpawnLife(x, y, score, delay){
SpawnItem(ITEM_LIFE_B, x, y, score, delay);
}
function SpawnLifePiece(x, y, score, delay){
SpawnItem(ITEM_LIFE_B_P, x, y, score, delay);
}
function SpawnSpell(x, y, score, delay){
SpawnItem(ITEM_SPELL_B, x, y, score, delay);
}
function SpawnSpellPiece(x, y, score, delay){
SpawnItem(ITEM_SPELL_B_P, x, y, score, delay);
}Code: [Select]case(EV_USER+1000){ // Spawn Item event
let args = GetEventArgument(0);
SpawnItem(args[0], args[1], args[2], args[3], args[4]); // type, x, y, score, delay
}
I don't get it, what should I do?
while(ObjEnemy_GetInfo(enm,INFO_LIFE)>=7000){
yield;}
while(ObjEnemy_GetInfo(enm,INFO_LIFE)<=7000 && ObjEnemy_GetInfo(enm,INFO_LIFE)>= 4500){
yield;}
you should write a more specific health check from the Boss that does something from A to B and if it passes the 1st threshold it will do the next from B to CThat's not what I want; what I'm looking for is nons/spells like this (https://www.youtube.com/watch?v=NYmDX8IyLXY)
Oh, now I understand, and I don't get why your SpawnLife/Spell is a function. Can't it be a task?They're pretty minor reasons. I really just did it for the semantics difference, it isn't important. The most significant thing for general use is that you can return values from functions but not tasks, so while I don't do it there you could restructure SpawnItem a bit to be a function that runs an internal task and returns the item object ID, then return that ID again from e.g. SpawnLife. That way you'd have access to the item object inside the event call if you needed it for whatever reason.
That's not what I want; what I'm looking for is nons/spells like this (https://www.youtube.com/watch?v=NYmDX8IyLXY)
Anyone mind helping me try to replicate some spells and nonspells so I can understand how they work?I can help you with some things, but I'm not an expert
I can help you with some things, but I'm not an expert
Is there a way to disable the item score?I don't know what you mean by this.
I am trying to figure out the best way to replicate something similar to Mokou's first non-spell, yet I can't seem to see if loose lasers or bullets are better to create the effect. Then if it would be better to use ascent loops or just to use regular loops. I still can't figure out how to make the bullets rotate in just one direction and not oscillate.Mokou's first non-spell? Why are you thinking about lasers; there are no lasers involved. The bullets also don't rotate? It's the firing angle that rotates. I don't know which pattern you're referring to with that description.
I don't know what you mean by this.Like take out the score that the item gives you, because if I set to 0, it still appears near the character.
Is there a way to disable the item score?
I don't know what you mean by this.
Mokou's first non-spell? Why are you thinking about lasers; there are no lasers involved. The bullets also don't rotate? It's the firing angle that rotates. I don't know which pattern you're referring to with that description.
This is the non spell I was talking about,(https://youtu.be/xl17uhqSuqc). What I meant was, I cannot figure out if I used CreateShotA1, how to get it to replicate similar effects to how it rotates around the boss and has multiple rows of bullets coming from three points.
How can I change the width (the actual width, not the render one) of a laser object (I'm using the objshot create and regist method).
task ShotU1{
while(true){
let las = -1;
if(Shooting){
let angleT= 270-2.5;
ascent(i in 0..2){
las = ObjShot_Create(OBJ_STRAIGHT_LASER);
ObjShot_Regist(las);
ObjShot_SetAutoDelete(las, false);
ObjShot_SetGraphic(las, 3);
ObjShot_SetDamage(las, 0.01);
ObjShot_SetPenetration(las, 3);
ObjLaser_SetLength(las, 512);
ObjLaser_SetRenderWidth(las,8);
ObjStLaser_SetAngle(las,angleT);
KeepAtObj(las,playerID);
angleT+=5;
deleteinloop(las);
}
yield;
}
yield;
}
}
task deleteinloop(las){
while(!Obj_IsDeleted(las)){
if(!Shooting){
Obj_Delete(las);
}yield;
}
}
task KeepAtObj(obj,obj1){
while(!Obj_IsDeleted(obj)){
ObjMove_SetPosition(obj,ObjRender_GetX(obj1),ObjRender_GetY(obj1));
yield;
}
}
I'm not really sure that's a good way to make a laser? If you look closely at, say, Marisa's lasers, they actually consist of small bullets being fired along coloured lines. I didn't even know you COULD make straightlasers that deal damage to enemies. The other problem is that you're creating a laser every single frame while the player is shooting, but only delete the lasers once the player stops shooting. Assuming that your way of making a player laser even works[Its much different then the method I use], you should be able to fix the stacking laser problem by replacing the yield after the ascent loop with while(shooting){yield;}. I'm also not sure why the ascent loop makes two lasers, since they both end up occupying the exact same location. Either make only one laser or have the lasers be in different places.I've see this way of laser at the Random Player Generator.
Is there a function to get the ID of the nearest enemy of the player?
I've got the ascent loops working how I want them to but I can't figure out how the bullets spin around Mokou.Hint: increment the angle using the loop variable as a parameter :)
task ShotU1{
while(true){
let las = -1;
let las1 = -1;
if(Shooting){
ascent(i in 0..1){
las = ObjShot_Create(OBJ_STRAIGHT_LASER);
ObjShot_Regist(las);
ObjShot_SetAutoDelete(las, false);
ObjShot_SetGraphic(las, 1016);
ObjShot_SetDamage(las, 5);
ObjShot_SetPenetration(las, 3);
ObjLaser_SetLength(las, 512);
ObjLaser_SetRenderWidth(las,20);
ObjLaser_SetIntersectionWidth(las,20);
ObjStLaser_SetAngle(las,270);
KeepAtObj(las,playerID);
deleteinloop(las);
ObjStLaser_SetSource(las,false);
Obj_SetRenderPriorityI(las,79);
}
while(Shooting&&!isFocus){
let angleT= 270-(360/72)*2;
ascent(i in 0..72/16){
let obj = CreatePlayerShotA1(ObjRender_GetX(ObjOption),ObjRender_GetY(ObjOption),5,angleT,10,1,879);
let obj1 = CreatePlayerShotA1(ObjRender_GetX(ObjOption1),ObjRender_GetY(ObjOption1),5,angleT,10,1,879);
angleT+=360/72;
ObjRender_SetColor(obj,0,0,0);
ObjRender_SetColor(obj1,0,0,0);
}
wait(5);
}
if(Shooting&&isFocus){
ascent(i in 0..1){
las = ObjShot_Create(OBJ_STRAIGHT_LASER);
ObjShot_Regist(las);
ObjShot_SetAutoDelete(las, false);
ObjShot_SetGraphic(las, 1016);
ObjShot_SetDamage(las, 5);
ObjShot_SetPenetration(las, 3);
ObjLaser_SetLength(las, 512+256);
ObjLaser_SetRenderWidth(las,20);
ObjLaser_SetIntersectionWidth(las,20);
KeepAtObj(las,ObjOption);
deleteinloop(las);
ObjStLaser_SetSource(las,false);
Obj_SetRenderPriorityI(las,79);
las1 = ObjShot_Create(OBJ_STRAIGHT_LASER);
ObjShot_Regist(las1);
ObjShot_SetAutoDelete(las1, false);
ObjShot_SetGraphic(las1, 1016);
ObjShot_SetDamage(las1, 5);
ObjShot_SetPenetration(las1, 3);
ObjLaser_SetLength(las1, 512+256);
ObjLaser_SetRenderWidth(las1,20);
ObjLaser_SetIntersectionWidth(las1,20);
KeepAtObj(las1,ObjOption1);
deleteinloop(las1);
ObjStLaser_SetSource(las1,false);
Obj_SetRenderPriorityI(las1,79);
while(!Obj_IsDeleted(las)&&!Obj_IsDeleted(las1)){
let enemy = GetAllEnemyID;
let dist = [];
let nearestID = 0;
let distA2 = [0];
ascent(i in 0..length(enemy)){
let distV = [GetDistance(ObjMove_GetX(enemy[i]),ObjMove_GetY(enemy[i]),GetPlayerX,GetPlayerY)];
dist = dist ~ distV;
}
ascent(i in 0..length(dist)){
let distnrst = min(dist[i],dist[max(i-1,0)]);
let distnrstA = [distnrst];
distA2 = distA2 ~ distnrstA;
if(distA2[i] == distnrst){nearestID++;}
}
ObjStLaser_SetAngle(las,GetAngleToObj(las,enemy[nearestID]));
ObjStLaser_SetAngle(las1,GetAngleToObj(las1,enemy[nearestID]));
yield;
}
}
}
while(Shooting){yield;}
}
yield;
}
}
My player doesn't change the focus shot when I change to unfocus, but changes the unfocus shot when I change to focus (this may be a little hard to understand).
Here is the code:Code: [Select]
A few things:1.I'm sorry, I didn't realize that it was so big.
First, please pastebin large blobs of code
Second, you have no comments or anything within your code designating your intention or what you are trying to do
Finally, I have no idea where this is being called from, how you are setting variable such as Shooting or isFocus, etc. Please provide more context for your problem.
1.I'm sorry, I didn't realize that it was so big.
2.Here is the code with a hell lot of comments (https://pastebin.com/3tiqEh5h).
3.It is in the comments above.
let x0 = 192; // center x-position
let y0 = 224; // center y-position
let r = 50; // radius
let a = 0; // angle
while(!Obj_IsDeleted(obj)){ // some loop
ObjMove_SetPosition(obj, x0 + r*cos(a), y0 + r*sin(a));
a++;
yield;
}
So I just noticed that loose lasers have to "extend" again anytime you set their position. Is there any way around this?It often makes sense for it to work this way due to the behaviour of the lasers. A bit weird this is mandatory, but I don't really think there's a proper way to get around it. Two options:
(I've got a sort of "tree" of loose lasers and I'd like to have them shake around a bit before breaking away. Currently I'm just changing their angle, but that makes the "tail" shake much more than the "head". Considering trying to seamlessly swap them out with straight lasers for the shaking around bit, but that wouldn't help if I wanted to actually change its position.)
It often makes sense for this to happen due to the behaviour of the lasers, but I don't really think there's a nice way to do so. Two options:
1) If you wanted to change its position once at max length, it would make sense to swap into a straight laser.
2) It is possible to set position, set speed to laser length, wait one frame then set speed back to 0, but this is pretty weird and you do need the one frame gap in between each move for the speed calc to apply.
Is there any place that I can learn how to make Dialogue?Or there is a "universal" template/function in here?You can make a dialogue by showing a image and text in a specific timing, and make that the player cannot shoot and can skip it with VK_OK.
That's probably impossible to do with the basic camera functions. I don't doubt that its possible to do that, but its definitely a far greater undertaking then just flipping the whole screen around.I think render targets should do it, but it is so complicated to mess with it.
How do I flip only one part of the camera, like half the screen is flipped?(I mean flip like Seija)
Looking for flipping the screen like with Seija?I think they were actually asking how to do that to only part of the screen.
I'm trying to create a Reimu player, but I can't make the player's sprite change when going to left or right.ObjMove_GetAngle isn't going to work for the player. Consider how the controls work: X and Y speed are controlled separately, so it won't work any more than it would for a shot that's been AddPatternB1'd (and there's no function to get X/Y speed, either, which is what I'm currently struggling with). And that's assuming it even uses speeds instead of just setting position.
Here's the player script (https://pastebin.com/sVsgkgkP), the shot data (https://pastebin.com/DKFm4uRb) and a collection of functions (https://pastebin.com/gfhD6vgC)
let L = GetVirtualKeyState(VK_LEFT )==KEY_HOLD || GetVirtualKeyState(VK_LEFT )==KEY_PUSH);
let R = GetVirtualKeyState(VK_RIGHT)==KEY_HOLD || GetVirtualKeyState(VK_RIGHT)==KEY_PUSH);
if( L && !R){ AnimLeft; }
else if(R && !L){ AnimRight; }
else{ AnimStill; }
Other notes:Instead, use GetVirtualKeyState(VK_LEFT/RIGHT). Something like:It works but the sprite keeps bugging(blinking or out scaling) each time it changes the directionCode: [Select]let L = GetVirtualKeyState(VK_LEFT )==KEY_HOLD || GetVirtualKeyState(VK_LEFT )==KEY_PUSH);
let R = GetVirtualKeyState(VK_RIGHT)==KEY_HOLD || GetVirtualKeyState(VK_RIGHT)==KEY_PUSH);
if( L && !R){ AnimLeft; }
else if(R && !L){ AnimRight; }
else{ AnimStill; }
It works but the sprite keeps bugging(blinking or out scaling) each time it changes the directionSome of your rects are messed up. The second one for left, (35, 50, 59, 141), and the second for right, (35, 98, 59, 93), seem to have their bottom borders swapped.
Every time I try to run my script as a plural script Danmakufu crashes. I can't figure out why it does.
We have no context. What script are you trying to run, and what do you mean by 'try to run my script as a plural script'? Without this information, it will be hard to help you. :)These are the pastebin uploads for all the files, what i meant was transferring the single scripts to a plural script and then running it, but every time I run it Danmakufu crashes.
These are the pastebin uploads for all the files, what i meant was transferring the single scripts to a plural script and then running it, but every time I run it Danmakufu crashes.
Attack.txt - https://pastebin.com/VgLW4V66
Eternallight.txt - https://pastebin.com/LGsNvRP3
Testtt.txt - https://pastebin.com/sR8kf6qE
BoWaP.txt - https://pastebin.com/FPrNwnBv
Plural script - https://pastebin.com/XRkhiapL
Hello, may I ask this again because it got buried on the last page before it was approved?Could you explain why you want to do it recursively in the first place? It shouldn't matter any more than regular recursion, as the tasks spawned recursively don't depend on the calling task once they're in the task scheduler. One main "advantage" to calling tasks in a loop is that you can have the arguments to the task depend on the loop context in some way, and this doesn't invade the task code itself. If you think there's a solid programming benefit to calling them recursively then it's probably fine. I haven't seen any particularly shallow recursion limit in DNH. That being said, recursion in general can be wasteful because you keep building up the call stack until the very end and you have to keep track of all deferred operations (i.e. there is no tail-call optimization).
I have a question regarding Danmakufu's tasks - Is there a performance/processing cost connected to calling tasks recursively, as opposed to repeating said tasks with loops?
Thanks in advance
E: Whatever is causing it definitely involves GetScreenWidth. I changed the screen size in th_dnh.def as a test and all affected objects went off the screen entirely.My measurements:
Could you explain why you want to do it recursively in the first place? It shouldn't matter any more than regular recursion, as the tasks spawned recursively don't depend on the calling task once they're in the task scheduler. One main "advantage" to calling tasks in a loop is that you can have the arguments to the task depend on the loop context in some way, and this doesn't invade the task code itself. If you think there's a solid programming benefit to calling them recursively then it's probably fine. I haven't seen any particularly shallow recursion limit in DNH. That being said, recursion in general can be wasteful because you keep building up the call stack until the very end and you have to keep track of all deferred operations (i.e. there is no tail-call optimization).Thank you for this insight.
That level of recursion is absolutely fine, you can definitely do that. I'm talking more on a very deep scale. In your example the bullets scale exponentially, but you still shouldn't have any trouble until the number of bullets gets to the point where it's ridiculous on screen anyways.Thank you lots and lots: This is a very clear and informative explanation. You've helped a lot! :) :) :)
Using return in a task is just the same as letting the task end. With recursive functions, the call stack can become large with deep recursion because each function has to keep track of the context it was called from and you have to wait for the function to complete to fold back. However like I wrote above, with tasks they only need to know that until they're put in the task scheduler. That is, control returns to the parent context once the task either finishes or yields. After this a task becomes detached from its parent context -- which is also the reason tasks can't return values.
Basically what that means is that for the most part if you're using recursive tasks you don't need to worry much about building up waste unless you're doing the recursion before any yields, which is usually not the case.
You can also reset the camera focal point with Reset2DCamera.You know, I tried that before setting it directly and nothing happened. I think I ran into a similar issue at some point in the past as well.
E: Now I've got another issue: The game crashes instantly upon trying to load my package. And by "instantly", I mean I put WriteLogs everywhere I could think of (including @Loading and global) and none of them got executed. The last thing written to the log is the message that it's trying to load a package script (パッケージスクリプト[path]) and then nothing. Not really sure what's going on, since it neither errors nor actually does anything. Same github (https://github.com/JonAjuhan/cs401Project)
If it's crashing immediately after selecting it, it is, from my experience, a parsing error in the script - some kind of thing you are doing that Danmakufu cannot comprehend and crashed trying to do so.It was an encoding issue! Apparently it somehow got encoded in UTF-16 (UCS-2 LE BOM). I got my clue when I was investigating why github was saying it was a binary file.
let append = "";
let qux = [0];
...Append is a reserved keyword, isn't it? ...Yep, it is. That was it. God dammit.It was an encoding issue! Apparently it somehow got encoded in UTF-16 (UCS-2 LE BOM). I got my clue when I was investigating why github was saying it was a binary file.Danmakufu actually supports UTF-16 LE w/ BOM, but does not read UTF-8. NPP interpreting UTF-16 as UCS-2 is not entirely correct but they're exactly the same up to a certain point.
...Except converting it to UTF-8 didn't fix it. It did cause the window to abruptly close instead of not responding, so it was probably a problem, at least.
Do the functions ObjMove_SetDestAtFrame/AtSpeed/AtWeight work on OBJ_ENEMY type objects?Enemy objects are a kind of Move object, so yes.
if(GetVirtualKeyState(ShiftKey) == KEY_PUSH || GetVirtualKeyState(ShiftKey) == KEY_HOLD && alive )
The && operator has a higher precedence than ||, so a || b && c works as a || (b && c). You need (a || b) && c for the correct behaviour.
while(ObjSound_IsPlaying(seobject)){ yield; }
Obj_Delete(seobject);
This isn't the best way to go about things (because it still creates new objects and loads the file every time) but it fixes your immediate problem.if(frame > ShotPerFrame){
frame = ShotPerFrame;
}
I can't really tell why this part is here because your shooting condition is already frame >= ShotPerFrame and at the end you set frame back to 0. It shouldn't be a problem it just doesn't make much sense.
Hi there,For package scripts you need to explicitly load the player into the package before being able to call it. A snippet from my own game:
Just a quick question. What does the error: "player not found" mean?
Originally when loading a player script in my Package script, the player script in the default player folder with the same name loads. And when I changed it, the error message comes out.
I tried loading other player scripts from the default folder and they work. But other player scripts from anywhere else I get the message.
Testing out the player script in single and stage menus of Danmakufu work fine. And the player script is located in a folder that is in the same folder as the Package script.
task initializeStage {
let pathBorder = "script/player/dcs_player/player_border.txt";
SetStagePlayerScript(pathBorder);
SetStageMainScript("script/thdcs/DanceContestStage.txt");
StartStageScene;
}
Two questions:Short answer: You can't. Restart you must.
- I'm finding that I have to restart my package entirely before any changes to whatever script I'm working on actually take effect. How might I go about making sure the script gets reloaded when I run it from my menu, the same way it does when you run a script from the default package?
For package scripts you need to explicitly load the player into the package before being able to call it. A snippet from my own game:Code: [Select]task initializeStage {
let pathBorder = "script/player/dcs_player/player_border.txt";
SetStagePlayerScript(pathBorder);
SetStageMainScript("script/thdcs/DanceContestStage.txt");
StartStageScene;
}
Basically my package runs this task, puts the player script in a variable called pathBorder. The key function here obviously is SetStagePlayerScript(); after that proceed as normal. Notice how my player script is located somewhere else, just like your scenario.
I never dived into the reason why the default script works so I cannot shed any light on this part.
Thank you for the help. ^^DHuh, that is odd. I am checking my own player script and it just reports the following headers: (garbled title/text is because of JP characters not visible on my mac)
I've tried loading the player script, but nothing happened. Then I also discover that apparently you also need to write #Player[playerpath] on the header.
Thank you again for the reply. It was very helpful.
#TouhouDanmakufu[Player]
#ScriptVersion[3]
#ID["DCS_BORDERTEAM"]
#Title["???E?`?[??"]
#Text["???E?`?[??"]
#ReplayName["BorderTeam"]
https://gist.github.com/drakeirving/b0d0a8400c1cfff80385f95e5d6d9d3e (https://gist.github.com/drakeirving/b0d0a8400c1cfff80385f95e5d6d9d3e)Oooh. That's some good stuff and gives me a lot of insight.
- Arrays are typedSo I've noticed - the big thing I need this for (apart from general use) is figuring out the type of arrays so I can safely append a hash to them before notifying events, which will use the hash to pass back a value through common data.
- Strings are character arrays, i.e. "abc" == ['a','b','c']I knew this was the case in other languages, but didn't want to assume the two were equivalent in Danmakufu. Good to have confirmation that they are.
- If you type [] inside a script it defaults to a char arrayDoes this mean [] and "" are functionally equivalent? If so, does it actually affect anything that they default to char arrays?
- Empty arrays can be turned into another type of array
- ? Infinity should be treated as valid numbers. NaNs also technically work without errors but have behaviour inconsistent with numbers.Doesn't ?INF00 also have behavior inconsistent with numbers? I believe anything you do to it can only result in ?INF00, IND00, or QNAN0. Still, I wouldn't want to accidentally skip appending something to an array just because it was divided by zero and end up with weird confusing behavior, so I see the value of treating it as a number.
The one consequence (https://www.shrinemaiden.org/forum/index.php/topic,16584.msg1189214.html#msg1189214) I know of is if you're trying to compare arrays; arrays with different types can't be compared even if one is empty. Please do not compare arrays with a literal [].Oh! Ooh! Several errors I've gotten in the past suddenly make sense.
You can "create" an empty non-char array with something like erase([1], 0)Oh, wow. I wasn't even thinking about that. That's one of those things that makes perfect sense but isn't intuitive if you don't already know it.
The magic is that ToString formats char arrays as strings and all other arrays with brackets. Slicing 0..0 gives you an empty array but the type remains, so either you get empty string or the string "[]".
Is there a danmakufu version that uses ScriptVersion[1]?
Oooh, ancient history. You're talking about stuff from over a decade ago. :)What? A DECADE ago?
Same difference. "I thought [version 2] was old".
2003/11/24: 0.00a (first public)
2004/01/26: 0.10a (first script v2)
2006/10/09: 0.12m (last script v2)
2010/05/05: ph3 α1 (first script v3)
2015/01/18: ph3 .1 pre6a (current)
2003/11/24: 0.00a (first public)Wow, it's been around for almost 15 years. Has it been the same people working on it the whole time? ...And are those people/anyone still working on it?
2004/01/26: 0.10a (first script v2)
2006/10/09: 0.12m (last script v2)
2010/05/05: ph3 α1 (first script v3)
2015/01/18: ph3 .1 pre6a (current)
Wow, it's been around for almost 15 years. Has it been the same people working on it the whole time? ...And are those people/anyone still working on it?
(Still wondering about changing the gray bars to black when fullscreened, btw.)
He'll give you some of it if you ask nicely, though.Eh, wait, really? I had thought it was totally closed-source. How much is "some of it"?
Hmm, I was trying to figure it out myself and looking some others scripts for "reference"... :blush:A dialogue is nothing more than drawing two 2D sprite images on your screen and showing/hiding them depending on the "dialogue". Like 2D sprite A -> Alpha 255 while sprite B is Alpha 55 (transparency).
Short Long Story : I can't figure dialogue.
Long Story : I know that it has do to do with pictures and frames, but I don't know where to start or any tutorial/easier example of...
Can I use a 3d model like a sprite?(I mean like a boss sprite, with it having animations and etc)Don't see why you can't. You just need to make sure the 3D model is following the object movement of your "invisible" boss object. (And making sure the collisions are set). About the animations, can't say.
Why I'm being "blocked"?
Is Danmakufu considered a difficult language to program compared to others?
Hi there,I can say that the first you are going to use area common data.
I'm currently stuck with two things I want to implement:
First is saving a highscore and spellcard-history. It should be something with CommonData, but I can't figure out how exactly I have to use that.
Second is textboxes. They are basically just pictures and text, some routine that waits for keyinput so the rest of the script can resume, but I can't get it working properly.
Help would be very appreciated, thanks!
First is saving a highscore and spellcard-history. It should be something with CommonData, but I can't figure out how exactly I have to use that.Look at 34th page of this thread, I've asked the similar question and the explanations given were pretty easy to understand
As for Unity and C#, making a Danmaku game in Unity probably takes 20x longer than making one in Danmakufu.Haha, I can say from experience, making a Danmaku game in Unity is indeed hard... (considering its totally unoptimized for this kind of use)
task SpamShot(obj){
let angleT = 90;
while(!Obj_IsDeleted(obj)){
loop(15){
let obj1 = CreatePlayerShotA1(ObjMove_GetX(obj)+64*cos(angleT),ObjMove_GetY(obj)+64*sin(angleT),6,angleT,1,1,5);
let obj2 = CreatePlayerShotA1(ObjMove_GetX(obj)+64*cos(-angleT),ObjMove_GetY(obj)+64*sin(-angleT),6,-angleT,1,1,5);
angleT+=360/15;
Obj_SetRenderPriorityI(obj1,25);
Obj_SetRenderPriorityI(obj2,25);
}
angleT+=2;
wait(2);
}
}
The missing variable is obj1 and obj2.So, I'm helping my friend (jao) to make a Reimu player script.
He doesn't know how to do bombs, so he gave me a copy of the player script to implement a bomb.
All should be working correctely, but Danmakufu tells that the variable is not defined.
I try everything to solve this, but it's no use.
Here's the code:Code: [Select]task SpamShot(obj){
The missing variable is obj1 and obj2.
let angleT = 90;
while(!Obj_IsDeleted(obj)){
loop(15){
let obj1 = CreatePlayerShotA1(ObjMove_GetX(obj)+64*cos(angleT),ObjMove_GetY(obj)+64*sin(angleT),6,angleT,1,1,5);
let obj2 = CreatePlayerShotA1(ObjMove_GetX(obj)+64*cos(-angleT),ObjMove_GetY(obj)+64*sin(-angleT),6,-angleT,1,1,5);
angleT+=360/15;
Obj_SetRenderPriorityI(obj1,25);
Obj_SetRenderPriorityI(obj2,25);
}
angleT+=2;
wait(2);
}
}
It's helpful to have the exact error message (i.e. a screenshot) so we can see what Danmakufu actually output and at what line.(https://cdn.discordapp.com/attachments/412784674964766720/450472543959384075/unknown.png)
Yep, so it's like I said. CreatePlayerShotA1 doesn't return the player shot object's ID, so the variable remains empty, and reports it as empty when you try to use it as an object ID.There's apparently also a CreatePlayerShotObjectA1 that DOES return an object ID. It doesn't seem to be documented anywhere. The arguments are the same: x,y,speed,angle,damage,penetration,graphic.
There's apparently also a CreatePlayerShotObjectA1 that DOES return an object ID. It doesn't seem to be documented anywhere. The arguments are the same: x,y,speed,angle,damage,penetration,graphic.I'll keep a note of this :|
There's apparently also a CreatePlayerShotObjectA1 that DOES return an object ID. It doesn't seem to be documented anywhere. The arguments are the same: x,y,speed,angle,damage,penetration,graphic.Was the function implemented?
function CreatePlayerShotObjectA1(x, y, speed, angle, damage, penetration, graphic){
let obj = ObjShot_Create(OBJ_SHOT);
ObjMove_SetPosition(obj, x, y);
ObjMove_SetSpeed(obj, speed);
ObjMove_SetAngle(obj, angle);
ObjShot_SetDamage(obj, damage);
ObjShot_SetPenetration(obj, penetration);
ObjShot_SetGraphic(obj, graphic);
ObjShot_Regist(obj);
return obj;
}
I'm very dumb sometimesCode: [Select]function CreatePlayerShotObjectA1(x, y, speed, angle, damage, penetration, graphic){
let obj = ObjShot_Create(OBJ_SHOT);
ObjMove_SetPosition(obj, x, y);
ObjMove_SetSpeed(obj, speed);
ObjMove_SetAngle(obj, angle);
ObjShot_SetDamage(obj, damage);
ObjShot_SetPenetration(obj, penetration);
ObjShot_SetGraphic(obj, graphic);
ObjShot_Regist(obj);
return obj;
}
wau
The wiki has been down for a few days now, any news?
The wiki has been down for a few days now, any news?Seems so.
Does anyone have a complete list of ph3 functions, because https://dmf.shrinemaiden.org/wiki/Functions_(ph3) isn't working for me
Alternatives:
http://www.geocities.co.jp/SiliconValley-Oakland/9951/pre/th_dnh_help_v3.html (http://www.geocities.co.jp/SiliconValley-Oakland/9951/pre/th_dnh_help_v3.html) (official Japanese docs)
https://web.archive.org/web/20170621193842/http://dmf.shrinemaiden.org:80/wiki/Functions_(ph3) (https://web.archive.org/web/20170621193842/http://dmf.shrinemaiden.org:80/wiki/Functions_(ph3))
https://sparen.github.io/ph3tutorials/docs.html (https://sparen.github.io/ph3tutorials/docs.html) (work in progress; incomplete)
I literally just linked the webarchive version of the wiki four posts ago :|
Hele: Not to mention I even answered another member about it too :V
A few questions:
Assuming it's not being looked after by the script, how far can a shot go off the playing field before it gets automatically deleted?
Does this happen immediately if a shot spawns/is teleported outside of this range?
Would there be a way to change this value without altering the size of the playing field?
1) 64 pixels on all sides (See: http://www.geocities.co.jp/SiliconValley-Oakland/9951/pre/th_dnh_help_v3.html )
2) For regular shots, you must set them to not auto delete via ObjShot_SetAutoDelete(obj, false);
3) Refer to SetShotAutoDeleteClip ( https://web.archive.org/web/20170522220913/http://dmf.shrinemaiden.org:80/wiki/Shot_Functions#SetShotAutoDeleteClip )
Thank you, and can this apply for all objects, not just shots?
task ObjMove_SetAutoDeleteClip(obj, left, top, right, bottom){
let l = -left;
let t = -top;
let r = GetStgFrameWidth() + right;
let b = GetStgFrameHeight() + bottom;
let x;
let y;
while(!Obj_IsDeleted(obj)){
x = ObjMove_GetX(obj);
y = ObjMove_GetY(obj);
if(x < l || x > r || y < t || y > b){
Obj_Delete(obj);
}
yield;
}
}
In the example, I have an image of a white pixel I use for a canvas, and a 256x256 image of a white circle on black background. I stretch the white pixel to 1024x512 (the render target size), and then repeatedly add copies of the circle texture with subtract blending. So the render target becomes a texture that is mostly white with a bunch of random black circles. Meanwhile, some background is drawn on layers 26 to 28. The Shader object applies the masking shader technique, using the render target as the applied texture, to the layers 26 to 28, which results in the background appearing as though there are holes in it that scroll across the screen.
I tried it, but it shows the black circles on a white background instead... what just happened? Also, what is that text "example_mask" as seen on the example you posted?To make the mask always transparent you need to remove Obj_SetVisible(contents, true); from the code below, so it won't be only black circles(atleast that's what I did and it works completely fine)
Can someone tell me...on the masking shader? I have no sense after I follow this example... Please Respond...
ascent(i in 0..length(contents)){
// Make visible when drawing to render target
Obj_SetVisible(contents[i], true);
RenderToTextureB1(texture_name, contents[i], (i==0));
// Otherwise invisible
Obj_SetVisible(contents[i], false);
}
To make the mask always transparent you need to remove Obj_SetVisible(contents, true); from the code below, so it won't be only black circles(atleast that's what I did and it works completely fine)Code: [Select]ascent(i in 0..length(contents)){
// Make visible when drawing to render target
Obj_SetVisible(contents[i], true);
RenderToTextureB1(texture_name, contents[i], (i==0));
// Otherwise invisible
Obj_SetVisible(contents[i], false);
}
As for "example_mask" it is just a name for a mask, you don't have to worry about it.
I tried removing it, but still looks like this:
It's hard to see the code that maybe it's misarranged because of the code. Can you show me an (full) example of it? Please respond.
My computer is warning me that this Forum has a security certificate error. Is this something I should be worried about?
1) 64 pixels on all sides (See: http://www.geocities.co.jp/SiliconValley-Oakland/9951/pre/th_dnh_help_v3.html )64 pixels from the STG frame set via commands or the screen (set via resolution)?
resource\script\lib\lib_value.dnh
as UTF-16 LE with BOM,however:resource\script\stage\st_system\lib_PauseScene.dnh
the code line#include "./lib_PauseFps.dnh"
the Dot should mean "resource\script\stage\st_system" but misunderstood by engine.// test.dnh
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["test"]
#include "./include.dnh"
#include "./include2.dnh"
@Initialize{}
@MainLoop{}
@Event{
alternative(GetEventType())
case(EV_REQUEST_LIFE){
SetScriptResult(1);
}
}
// include.dnh
function a{
AddScore(1);
RaiseError("东方");
}
// include2.dnh
function b{
AddScore(1);
RaiseError("东方");
}
Sorry for long codes,for some reason I cannot access pastebin.Here's a simple file tree:
resource
├bgm //BGM
├img //Pictures
├player
│├CommonData
│└th12
│ ├pl00 //Player Script "Reimu"
│ │├pl00_MainShotTask.dnh
│ │├pl00_OptionTask.dnh
│ │├pl00_Player.dnh
│ │├pl00_SpellCard.dnh
│ │└pl00_SubShotTask.dnh
│ ├...
│ ├pl06
│ └CommonBomb.dnh
├script
│├lib
││└lib_value.dnh
│└stage
│ ├bg
│ ├enemy
│ ├scl
│ │└stage1_scl.dnh
│ ├st_system
│ │├lib_PauseScene.dnh
│ │└lib_PauseFps.dnh
│ ├lib_manual.dnh //Maunal Scene
│ ├lib_MusicRoom.dnh //MusicRoom Scene
│ └musiccmt.txt //MusicRoom Comments
└se //Sound Effect
// lib_value.dnh, Originally Shift-JIS
let CurrentFont = "飴鞭ゴシック等幅-04";//ゲームの共通フォント(The default font in the game)
let CurrentFontP = "飴鞭ゴシック等幅-04";//スペルカード名の共通フォント(The default font for spellcards' name)
---------->>>
// Saved as UTF-16 LE BOM
let CurrentFont = "黑体";//ゲームの共通フォント(The default font in the game)
let CurrentFontP = "黑体";//スペルカード名の共通フォント(The default font for spellcards' name)
#Include file is not found[<Game>/resource/script/stage/lib_PauseFps.dnh].
<Game>/resource/script/stage/lib_Manual.dnh
lib_Manual.dnh line(行)=282
↓
#include "./lib_PauseFps.dnh"
// lib_PauseScene.dnh
#include "resource/script/lib/lib_files.dnh"
#include "resource/script/lib/lib_v0.12m_Effect.dnh"
#include "resource/script/lib/lib_SpellIndex.dnh"
#include "resource/script/stage/lib_SpellResult.dnh"
#include "resource/script/stage/lib_Manual.dnh"
#include "./lib_PauseFps.dnh"
Yeah here cause a problem,it is ok before I encode lib_value.dnh as UTF-16 LE BOM,but crashed after I did it.That's strange.#Include file is not found[<Game>/resource/player/CommonData/pl00_MainShotTask.dnh].
<Game>/resource/player/CommonData/GaugeEffectTask.dnh
GaugeEffectTask.dnh line(行)=1588
↓
#include "./pl00_MainShotTask.dnh"
#include "./pl00_OptionTask.dnh"
#include "resource/player/th12/CommonBomb.dnh"
#include "./pl00_SpellCard.dnh"
And the file pl00_Player.dnh// pl00_Player.dnh
#TouhouDanmakufu[Player]
#ScriptVersion[3]
#ID["Reimu"]
#Title["Reimu"]
#ReplayName["Reimu"]
#include "resource/script/lib/lib_usershot_th128.dnh"
#include "resource/script/lib/lib_v0.12m_function.dnh"
#include "resource/script/lib/lib_files.dnh"
#include "resource/script/lib/lib_Event.dnh"
#include "resource/script/lib/lib_ItemConst.dnh"
#include "resource/player/CommonData/LocalData.dnh"
#include "resource/player/CommonData/Spell_back.dnh"
#include "resource/player/CommonData/StatusIrregular.dnh"
#include "resource/player/CommonData/SlowEffectTask.dnh"
#include "resource/player/CommonData/GaugeEffectTask.dnh"
#include "./pl00_MainShotTask.dnh"
#include "./pl00_OptionTask.dnh"
#include "resource/player/th12/CommonBomb.dnh"
#include "./pl00_SpellCard.dnh"
#Include file is not found[<Game>/resource/script/bg/bg_st1.dnh].
<Game>/resource/script/stage/lib_StageInclude.dnh
lib_StageInclude.dnh line(行)=270
↓
#include "./../bg/bg_st1.dnh"
#include "./lib_Stage1.dnh"
#include "./../enemy/lib/sp_bg/background_st1.dnh"
// stage1_scl.dnh
#TouhouDanmakufu[Stage]
#ScriptVersion[3]
#System["./../st_system/system.dnh"]//ここのシステム呼び出しは必須
#include "./../lib_StageInclude.dnh"
#include "./../bg/bg_st1.dnh"
#include "./lib_Stage1.dnh"
#include "./../enemy/lib/sp_bg/background_st1.dnh"
Here comes interesting thing, lib_StageInclude.dnh is found but bg_st1.dnh cannot found,and just caused by a encoding?
[...]
#Title["test"]
function a{
AddScore(1);
RaiseError("东方");
}
function b{
AddScore(1);
RaiseError("东方");
}
@Initialize{}
[...]
// lib_files.dnh
//カレントディレクトリ
let DIR_EXE = GetFileDirectory(GetMainPackageScriptPath);
let DIR = DIR_EXE~"resource/";
let FONT_DAT = DIR ~"img/font.dat";
let SyFontPath = DIR ~"img/font/amemuchigothicmono-b.ttf";
let SyFontBPath = SyFontPath;
#include "./lib_value.dnh"
#include "./lib_juicevalue.dnh"
And lib_files.dnh is included by other scripts that for some system-like using (e.g.players, PauseScene.dnh)Hello, I'd like some help with something I want to do in Touhou Danmakufu 0.12.
I want to make a row of bullets vary more in angle if the player gets closer to the boss. (Think Touhou 6 Stage 5 before the Sakuya Midboss.)
Is this possible? Or should I upgrade to ph3?
Is it possible? Yes. Do I remember exactly how to do it and which 0.12m functions to use? Not really. (cough cough please use ph3 - 0.12m is so old that pretty much nobody uses it anymore)
...
Regardless of engine, here's how it would work:
You will need to get the boss's position and the player's position, use the distance formula to calculate the distance between the two, and then utilize that number to control whatever parameters you need. In ph3, that's going to mean GetPlayerX/Y and ObjMove_GetX/Y.
How you scale the angle based on the distance is up to you as a designer.
if(subattack == 1 && count % 1 == 0 && count >= 0 && count % 240 < 20){
let angle = GetX - GetPlayerY;
let speed = 3;
loop(10){
ascent(i in 0..1){
CreateShotA(2, GetX, GetY, i*4);
SetShotDataA(2, 0, speed, angle, 0, 0, 3, BLUE01);
FireShot(2);
}
angle += 360 / 10;
}
}
task SpawnRings{
let randoffset = rand(0,360);
let numshiki = [6, 6, 8, 9];
ascent(i in 0..numshiki[diff]){AnchorBullet(randoffset+i*360/numshiki[diff]);}
}
This task runs numshiki instances of the AnchorBullet task. task AnchorBullet(ang){
let obj = CreateShotA2Alt(GetEnemyX(objBoss), GetEnemyY(objBoss), 3, ang, -0.05, 0, S_LAURAORB_DARKBLUE + S_AO, 0);
let objcount = 0;
ObjShot_SetSpellResist(obj, true);
while(ObjMove_GetSpeed(obj)>0){yield;}
let randoffset = rand(0,360);
let numinring = [5, 6, 8, 9];
let numinline = [2, 3, 5, 6];
ascent(i in 0..numinring[diff]){//greater om higher difficulties.
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;}//Default kill to prevent (0,0) spawning
ascent(j in 0..numinline[diff]){
let obj2 = CreateShotA1Alt(GetEnemyX(objBoss), GetEnemyY(objBoss), 0, 0, S_DKSUPP_DARKBLUE, 0);
BulletCommandsA1(obj2, obj, i, numinring[diff], j, randoffset);
}
GS(SFX_WAVE);
objcount++;
yield;
}
loop(150){//wait for last suppository to fire
objcount++;
yield;
}
Obj_Delete(obj);
}
This task creates 'parent' bullets. Each parent bullet runs the double ascent loop to create 'child' bullets. task BulletCommandsA1(obj, parent, ID, numinring, rowID, offset){
ObjMove_SetDestAtFrame(obj, ObjMove_GetX(parent)+30*cos(ID*360/numinring), ObjMove_GetY(parent)+30*sin(ID*360/numinring), 60);
let objcount = offset;
descent(i in 1..60){
ObjMove_SetDestAtFrame(obj, ObjMove_GetX(parent)+30*cos(ID*360/numinring+objcount), ObjMove_GetY(parent)+30*sin(ID*360/numinring+objcount), i);
objcount++;
yield;
}
loop(90){
ObjMove_SetAngle(obj, ID*360/numinring+objcount);
ObjMove_SetPosition(obj, ObjMove_GetX(parent)+30*cos(ID*360/numinring+objcount), ObjMove_GetY(parent)+30*sin(ID*360/numinring+objcount));
objcount++;
yield;
}
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;}//Default kill to prevent (0,0) spawning
ObjMove_SetSpeed(obj, 2+rowID/6);
}
The 'child' bullets constantly set their destination via ObjMove_SetDestAtFrame to be relative to their parent object. This allows them to spawn from anywhere on the screen and move towards their specified parent object. These particular shots rotate around their parent object for a while before flying off. @MainLoop {
SetCollisionA(GetX, GetY, 24);
SetCollisionB(GetX, GetY, 24);
task Bullet(x, y, v, angle) {
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, x, y);
Obj_SetAngle(obj, angle);
Obj_SetSpeed(obj, v);
ObjShot_SetGraphic(obj, RED01);
ObjShot_SetDelay(obj, 0);
ObjShot_SetBombResist(obj, true);
}
if(count == -60){
CutIn(KOUMA, "Wood Sign: Syphlae Horn (Easy)", Rumia, 0, 0, 0, 0);
}
count++;
yield;
}
@DrawLoop {
DrawGraphic(GetX, GetY);
}
@Finalize {
DeleteGraphic("script\img\ExRumia.png");
}
}
You need to call ObjShot_Regist to activate a shot object.
How?
?
You just use ObjShot_Regist(obj) after you create the object. This "activates" the shot which basically means it's fired.
case(1){
return [
"The Sky Wanders Closer",
"
The stage 1 theme.[r][r]
It's raaaaining. But it's not really a bleak kind of rain.[r]
It's weird to see fairies in Gensokyo with any half-decent intelligence.[r]
But it doesn't make a difference.
"
];
}
case(1){
return [
"天空越来越近",
"
The Sky Wanders Closer / 1面主题曲。[r][r]
天's raaaaining. But it's not really a bleak kind of rain.[r]
Nothing happend.天月 raaaaining. But it's not really a bleak kind of rain.
Nothing happend again. Even:天在下??雨 But it's not really a bleak kind of rain.
Nothing happend,either.case(1){
return [
"天空越来越近",
"The Sky Wanders Closer / 1面主题曲。[r][r]
天上在下----雨,但并不是那种阴冷的雨。[r]
见到幻想乡的那些还算有点智慧的妖精是不可思议的。[r]
但是这没什么区别。
"
];
}
case(1){
return [
"天空越来越近",
"The Sky Wanders Closer / 1面主题曲。[r][r]
天在下??雨,但并不是那种阴冷的雨。[r]
见到幻想乡的那些还算有点智慧的妖精是不可思议的。[r]
但是这没什么区别。
"
];
}
What do i need to do to get a notification that stage script is closed? I've tried various methods with CommonData, but none of them worked. @Finalize doesn't seem to work in stage scripts at all, since nothing I write there is ever executed. So I've come to the problem of needing a notification upon the closure of the stage, but none of the methods I know work.
Show us what you are currently doing with a MVCE (https://stackoverflow.com/help/mcve). Without seeing your code, it will be difficult to diagnose your problem.
So, the amount of code is gonna be quite big, since atleast 3 scripts are connected here. I guess I should explain what am I trying to do first. The main script here is a package (it's main menu to be exact). I've made a mask in that package for some VFX, no problems were detected here. Then there is a background script for a stage, which also uses the same type of mask for similar VFX, and when it comes to using it in the stage itself, it works perfectly fine. However, if I return to the main menu of the package after mask was used in the stage, some bugs are caused. After some testing, I managed to figure out that the cause of the bugs is infact the mask used in stage, and to get rid of them I just have to remove the mask and do some other stuff upon closing the stage. Heres where the main problem kicks in. If I finish the stage, everything works fine, but if I close the stage in the middle of the fight with a boss, the aforementioned bugs occur and I can't find a way to detect the closure of the script.
Firstly, if you are starting a shader in the package and then start the *exact* same shader again in the background, you may be applying it twice - it may be beneficial to have a CommonData flag that notes if the shader has already been started.I don't quite understand what do you mean by that.
Secondly, as long as you can get the Stage script's ID and pass it to the Background script, you may be able to use IsCloseScript() (https://sparen.github.io/ph3tutorials/docs.html#fxn_IsCloseScript).I did already try using IsCloseScript in the background, but for some reason it doesn't work. I have SetCommonData("StageID", GetOwnScriptID()); in the Initialize of stage script and something like this in StageBackground
while(!IsCloseScript(GetCommonData("StageID", 0))){
yield;
}
ClearInvalidRenderPriority();
but the while loop never stops running, even if I close stage script. That ClearInvalidRenderPriority(); is pretty much essential for me, since it needs to be called whenever stage script is closed, but nothing I know works.
Here are the scripts I use:I don't think posting them whole would do much, since there are a lot of interconnected scripts and they use a lot of images
Package (https://pastebin.com/03fTffUQ), StageBackground (https://pastebin.com/hq5wJvNP) and Stage (https://pastebin.com/0DRRTxRm)
I can't confirm that at the moment, but regardless if needed you can use ObjLaser_SetIntersectionWidth to set it manually.
Thanks,
I'm trying to incrementally decrease the width of a straight laser over time, so as an alternative, is there a way to alter the existing intersection width relative to the current hitbox width?
(Or relative to the render width may also work?)
let EatShots = GetShotIdInCircleA2(spawnX+length*cos(angle)/2,spawnY+length*sin(angle)/2,width/2,TARGET_ENEMY);
ascent(i in 0 .. length(EatShots)){
if(ObjShot_GetImageID(EatShots[i]) == 44){
Obj_Delete(EatShots[i]);
}
}
I'm having trouble with the following lines of codeCode: [Select]let EatShots = GetShotIdInCircleA2(spawnX+length*cos(angle)/2,spawnY+length*sin(angle)/2,width/2,TARGET_ENEMY);
ascent(i in 0 .. length(EatShots)){
if(ObjShot_GetImageID(EatShots[i]) == 44){
Obj_Delete(EatShots[i]);
}
}
It seems that the second line in that block returns the error:
")" is necessary
Why does this happen, and how can it be fixed?
I don't know if this is the solution, but in an ascent loop avoid having spaces before and after the ..?
Normally those spaces do not cause a problem, and removing them hasn't resolved issue here. :(
Provide the code before the code you just posted. There might be a missing semicolon, or you might be missing a comma somewhere.
task SnakeAnime(spawnX,spawnY,speed,angle){
let count = 0;
let delay = 50;
let startLength = speed*delay/2;
let startWidth = delay/2;
let length = startLength;
let width = startWidth;
let hitbox = startWidth-2;
let obj = CreateStraightLaserA1(spawnX,spawnY,angle,length,width,delay,72,0);
ObjStLaser_SetSource(obj,false);
while(!Obj_IsDeleted(obj)){
ObjLaser_SetLength(obj,length);
ObjLaser_SetRenderWidth(obj,width);
ObjLaser_SetIntersectionWidth(obj,hitbox);
length -= startLength/delay;
width -= startWidth/delay;
hitbox -= (startWidth-2)/delay;
if(count < 4 || width < startWidth/2){
ObjShot_SetIntersectionEnable(obj,false);
}
else{
ObjShot_SetIntersectionEnable(obj,true);
if(count > 4){
let EatShots = GetShotIdInCircleA2(spawnX+length*cos(angle)/2,spawnY+length*sin(angle)/2,width/2,TARGET_ENEMY);
ascent(i in 0..length(EatShots)){
if(ObjShot_GetImageID(EatShots[i]) == 44){
Obj_Delete(EatShots[i]);
}
}
}
}
if(count >= delay || width < 0){
Obj_Delete(obj);
}
count++;
yield;
}
}
Code: [Select]
This is the task that contains the section. Is this enough, or should I provide the entire script?
I thought I was hallucinating at that error
The issue is that length is a reserved keyword in Danmakufu, and you are redefining it in the function. Replace all occurrences of your local variable length with something else.
Refer to https://sparen.github.io/ph3tutorials/ph3u1l5.html#sub9 for more info - I'll update the section as well
Hi, sorry if this showing as a reply is just that I'm new in posting stuff in websites like this one.
Is just that I've got a problem that has been bugging me for weeks, you see I'm VERY new at this.
The problem is that every time I'm trying to use this Sparen Style script that I copied while watching the How to make Circles and Ellipses video, plus by following the tutorials of the Danmakufu ph3 tutorial website, when I try it, it always give me the: "GetCenterX is not defined". error.???
https://pastebin.com/rmHmLv8s (https://pastebin.com/rmHmLv8s)
And the same error is on many other codes for example:Code: [Select]task ParametricRing(){
let angleT = 0;
loop(30){
CreateShotA1(ObjMove_GetX(objBoss) + 90*cos(angleT), ObjMove_GetY(objBoss) + 90*sin(angleT), 2, angleT, 1, 0);
angleT += 360/30;
}
Preventing me from knowing if the codes I'm making have a failure or not.
Can somebody help me please :ohdear:
And I don't wanna bother but can somebody give me a curve laser code as well and tell me why the BGM that I put is not working please. :(
Where can I find a collection of the "dot" bosses sprites?
Or a link with all of them?
"dot" is just a term for pixel art.The main link server is down....
You might also be referring to KMAP's stuff, which are linked on the Japanese DNH wiki here under 敵画像:
http://danmakufu.wiki.fc2.com/wiki/素材リンク
How do I make bullets ricochet off of walls only once?
Assuming you've already watched the wall bouncing video tutorial, all you need to make them bounce exactly once is have a task that first waits for the bullet to hit a wall, and then performs the bounce. The task terminates then, and no more bouncing is performed.
Otherwise, refer to the tutorial at https://www.youtube.com/watch?v=eoOlDcWmGjc
Warning: Old tutorial, may contain cringe
The logic and structure is the same, you just have to translate which function does what.
You really should just learn ph3 though. You're using a program that's been deprecated for many years.
let outputfile = ObjFile_Create(OBJ_FILE_TEXT);
let outputfilepath = OUTPUT_DIRECTORY ~ "apmfps-" ~ starttime ~ ".csv";
ObjFile_OpenNW(outputfile, outputfilepath);
...
// Flush to file
ObjFileT_AddLine(outputfile, csvlog);
ObjFile_Store(outputfile);
WriteLog("APM_StartFPS: Wrote CSV to " ~ outputfilepath);
Obj_Delete(outputfile);
// yield once before marking as complete
yield;
finished_fps = true;
WriteLog("APM_StartFPSDEBUG: Finished");
while (!finished_fps) {yield;} //Wait for file to be written before reading
ObjFileT_AddLine(outputfile, APM_ChartGenFPS);
function APM_ChartGenFPS {
WriteLog("APM_ChartGenFPS: Starting.");
let svg = SVGChartGen;
let paths = [];
let maxfps = 0;
let filepath = OUTPUT_DIRECTORY ~ "apmfps-" ~ starttime ~ ".csv"; // Current run
//filepath = OUTPUT_DIRECTORY ~ "apmfps-20180627142126.csv"; //debug
let datapoints = CSVtoArray(filepath);
maxfps = maxarr(datapoints);
WriteLog("APM_ChartGenFPS Debug: Maximum FPS is " ~ ToString(maxfps));
...
}
function CSVtoArray(filepath) {
WriteLog("CSVtoArray: Running on " ~ filepath);
let handle = ObjFile_Create(OBJ_FILE_TEXT);
let status = ObjFile_Open(handle, filepath);
while (!status) {
//WriteLog("CSVtoArray: Reading file " ~ filepath ~ " failed.");
status = ObjFile_Open(handle, filepath);
yield;
}
WriteLog("CSVtoArray: Successfully read file " ~ filepath ~ ".");
let toreturn = [];
ascent(i in 0..ObjFileT_GetLineCount(handle)) { // For every line
let line = ObjFileT_GetLineText(handle, i + 1); // Recall that lines are 1-indexed
let split = SplitString(line, ",");
ascent(j in 0..length(split)) {
toreturn = toreturn ~ TrimString(split[j]);
}
}
Obj_Delete(handle);
return toreturn;
}
The code, when run, never gets past the infinite while loop - status is never set to true, the Success message never prints. Even after the file has shown up in my computer and I can open it, ObjFile_Open continues to fail.APM_StartFPS: Wrote CSV to Z:/Users/andrewfan/Desktop/THDNH ph3pre6a/script/ Sparen DNH APM/test/./dnhapm-output/apmfps-20180627144737.csv
2018/06/27 14:47:40.765 APM_StartFPSDEBUG: Finished
2018/06/27 14:47:40.775 APM_ChartGenFPS: Starting.
2018/06/27 14:47:40.787 CSVtoArray: Running on Z:/Users/andrewfan/Desktop/THDNH ph3pre6a/script/ Sparen DNH APM/test/./dnhapm-output/apmfps-20180627144737.csv
2018/06/27 14:47:42.648 force terminate
As you can see in the above, it's *writing* properly, and CSVtoArray is running on the same file path as the file that was written. However, ObjFile_Open fails continuously in the while loop. I can confirm that the file exists locally. And if I hardcode the filepath, ObjFile_Open actually works (see the debug statement in APM_ChartGenFPS).let file = ObjFile_Create(OBJ_FILE_TEXT);
let path = GetCurrentScriptDirectory() ~ "aaa.txt";
ObjFile_OpenNW(file, path);
ObjFileT_AddLine(file, "aaaaaa");
ObjFile_Store(file);
Obj_Delete(file);
yield;
file = ObjFile_Create(OBJ_FILE_TEXT);
let status = ObjFile_Open(file, path);
Is it possible to make a small square in which everything is rotated 180 degrees? Like Seija's spells, but only a fraction of the screen.
This minimal example:Code: [Select]let file = ObjFile_Create(OBJ_FILE_TEXT);
let path = GetCurrentScriptDirectory() ~ "aaa.txt";
ObjFile_OpenNW(file, path);
ObjFileT_AddLine(file, "aaaaaa");
ObjFile_Store(file);
Obj_Delete(file);
yield;
file = ObjFile_Create(OBJ_FILE_TEXT);
let status = ObjFile_Open(file, path);
if (!status) {
RaiseError("file not found");
}
The error was raised.You can snap a render target of the screen,What do you mean by that?
I know it sound a little dumb, but, I can't figure it out what is idle and moving animation...
If you can, please enumered it or tell me the order... :blush: :blush:
What do you mean by that?
The problem seems to be that you're calling renderplayer2 nine times in an ascent loop, but without actually using i, which is the whole point of the ascent loop. You're just calling the function with 9/360 as the angle nine times. If you changed it to use i*num_options/360 instead of num_options/360, you should end up with a circle of evenly spaced options.
Greetings again,
I'm kind of at my wits end since it took me this long to figure out how to use parameters (and eventually figured it out after a long time struggling), but now I face a new challenge. Remember "rendernightmare"? Well now it's renamed "renderplayer2(angle)" with the same content as render nightmare, but with added stuff such as the parameters.
Link 1 : https://ibb.co/deLp6d
opdup is the thing that you gave me to try to duplicate the options by 9, but it doesn't seem to work as planned, but at least it didn't give me errors.
link 2:https://ibb.co/jaGJzy
Just for more context, I had to declare an angle variable in line 21 since Danmakufu kept nagging me that "angle" was not defined. Since I did it was asked, it ran. However, it's didn't give me the desired result and it seems that it didn't do anything at all but give me just one option.
Before you tell me to look at tutorials, I came here because I looked at the tutorials, tried everything, and I couldn't come up with a solution. Can you please solve this conundrum?
Thank you so much if you do reply to this.
let number = [0,0,0,0,0,0,0];
loop{
while(number[0]==number[1]||number[0]==number[2]||number[0]==number[3]||number[0]==number[4]||number[0]==number[5]||number[0]==number[6]){
number[0] = floor(rand(1,8));
}
fire(number[0]);
number[6] = number[5];
number[5] = number[4];
number[4] = number[3];
number[2] = number[1];
number[1] = number[0];
yield;
}
"fire()" is the function that calls the patterns from 1 to 7.
So you want every pattern definitely to appear but only once and the order is random each time you boot up the spell card?Yes, basically. Sorry if I explained it badly :V
If I understood the problem correctly, it's that there's no number[3] = number[2]; in your script, so it just stops recording values further than the 3rd slot....Thanks, it worked. Wow, I feel so dumb now.
let number = shuffle([0,1,2,3,4,5,6]);
function shuffle(a){
let j; let tmp;
descent(i in 1..length(a)){
j = floor(rand(0, i+1));
tmp = a[i]; // swap i and j
a[i] = a[j];
a[j] = tmp;
}
return a;
}
So, is there any clue to why would the history not advance from 00/xx even after I managed to have the spell captured?
Exhibit 1, captured immediately after capturing the spellcard shown in Exhibit 2. (https://i.imgur.com/kCVuH8j.jpg)
Exhibit 2, snapped after the capture, in both sense, that is Exhibit 1. (https://i.imgur.com/pC4ikrh.jpg)
The entire budding work, I guess. (https://mega.nz/#!6s0h2SyS!rt2_2BNZn82aImKz1--0yEhYqvrD-zByF43QIFByj8A)
(BTW, if it gets released, Warusame is meant to stay in the final work. The gist of the plot is that Tsurubami [as in LE's Tsuru], the local admiral, hires the Gensokyan PC as a mercenary for 'questionable operations' to keep their shipgirl's hand clean from said questionable operations. Considering abyssals and danmaku don't [canonically] mix~)
//Anything Before?
case(EV_REQUEST_IS_LAST_SPELL){
//What I need to do here, to make a LastSpell?
}
//Anything After?
Code: [Select]//Anything Before?
case(EV_REQUEST_IS_LAST_SPELL){
//What I need to do here, to make a LastSpell?
}
//Anything After?
Please explain how to make a Last Spell, like IN (Hit => end)
How exactly does ObjMove_SetDestAtWeight calculate the slowing down? Is the weight how long it takes to slow down? Or maybe the distance to the destination when it starts to slow down?The algorithm for ObjMove_SetDestAtWeight is
Asking this because apparently Danmakufu crashes if you delete bullets while this funtion is active, so I'm going to create my own.
if dist < maxspeed * weight :
speed = dist / weight
else :
speed = maxspeed
If I'm corect, there is some programmes to make 3D backgrounds for danmakufu (like in the sample), but I don't remember the names. What are they? And is there any english tuturials for them?
Please provide a MINIMAL, complete, and verifiable example (https://stackoverflow.com/help/mcve). What you're asking is not clear at all - what do the two screenshots have to do with spell history? What library are you using?
What's the best way to get the ID's of shot objects within a rectangular area?What is the context? There is a general-purpose answer but it might be simpler based on what you're actually trying to do.
This is assuming that the rectangle is of any orientation, but the coordinates of the corners of the rectangle are known.
Hi,
What's the best way to get the ID's of shot objects within a rectangular area?
This is assuming that the rectangle is of any orientation, but the coordinates of the corners of the rectangle are known.
What is the context? There is a general-purpose answer but it might be simpler based on what you're actually trying to do.
What is the context? There is a general-purpose answer but it might be simpler based on what you're actually trying to do.
I'm supposing creating a StB-like engine. I don't have the exact math on me as I post this, but:
Assuming you don't need to take the radii of bullets into consideration (i.e that you simply wish to detect whether the center of a certain bullet is inside a rectangular area), since that requires the logic easiest to figure out, you'd need the following procedure:
(http://puu.sh/ATP8f/2f2e2ff62a.png)
Suppose ma and mb are the midpoints of a1 and a2, and of b1 and b2, respectively. Then M is the midpoint of ma and mb, thus being the center of the rectangle in question.
So then, you'd have an infinite line marked in red (it's not shown on the diagram, but let's call it L) intersecting ma and mb, and point P2 is the point on L that is closest to P, which is your bullet.
To check whether the bullet is in the rectangular area, check for two things:
- that the distance between P and P2 is no more than the distance between ma and a1 (or a2 -- they're the same, as well as mb and b1 or b2)
- that the distance between P2 and M is no more than the distance between M and ma (or mb.)
There's probably an error somewhere in there, but hopefully someone will have detected it before I get home.
// `poly` is an array of points like [[x1,y1], [x2,y2], [x3,y3], [x4,y4]] where edges connect between two adjacent points
function is_collided_polygon(x, y, poly){
let wn = 0;
poly = poly ~ [poly[0]]; // connect edge from last to first vertex
ascent(i in 0..length(poly)-1){
if(poly[i][1] > y){
if(poly[i+1][1] <= y){ // ascending edge crossing point
if(point_edge_side(x, y, poly[i][0], poly[i][1], poly[i+1][0], poly[i+1][1]) < 0){ // point left-hand of edge
wn--;
}
}
}else{
if(poly[i+1][1] > y){ // descending edge crossing point
if(point_edge_side(x, y, poly[i][0], poly[i][1], poly[i+1][0], poly[i+1][1]) > 0){ // point right-hand of edge
wn++;
}
}
}
}
// winding number of 0 iff point outside polygon
return (wn != 0);
function point_edge_side(px, py, ax, ay, bx, by){
// AB.x * AP.y - AB.y * AP.x
return ( (bx - ax) * (py - ay) - (by - ay) * (px - ax) );
}
}
function is_collided_rect(x, y, poly){
return is_point_projected_line(x, y, poly[0][0], poly[0][1], poly[1][0], poly[1][1])
&& is_point_projected_line(x, y, poly[1][0], poly[1][1], poly[2][0], poly[2][1]);
function is_point_projected_line(px, py, ax, ay, bx, by){
let abx = bx-ax;
let aby = by-ay;
let proj = (px-ax)*abx + (py-ay)*aby;
let magn = abx*abx + aby*aby;
return (proj > 0 && proj < magn);
}
}
I'm going to just drop a bunch of stuff because I wanted to explain it all and implement it myself...
I use an array here partially because the first method generalizes to polygons with however many vertices, and partially because I didn't want the function call to have a ton of extra coordinate parameters. Some more things to consider...
Is there a way to scale the image of a bullet, in a custom shotsheet, without having to change the original picture?No. Is there any reason you want to do this, when you can just resize the image in a graphics editing program?
So I've seen either of these videos: https://youtu.be/geTVIgDEO-Y?t=369 (https://youtu.be/geTVIgDEO-Y?t=369) -/- https://youtu.be/oDJpkTZQOiA?t=916 (https://youtu.be/oDJpkTZQOiA?t=916) , and I want to know what implements the slashing effect that cuts off the screen/stage frame and even the bullets (kinda like Yaorochi's sword cutting off the screen during the true final spell scard from Len'en 2).
Can you give me a detail and how is it implemented in coding? I want to know so that I can learn it.
Anyone out there, please respond, thank you. :wat:
You snap a render target of the background layers and turn it into two primitive objects that you move in opposing directions. You will want to put a layer of black underneath the sliding primitive objects to cover the original background, which will need to transition to the original background afterwards.
Note: For reference, I think gtbot did this sometime a few years back along with a replica of Yabusame's bomb effect.
task gravity(){
while(!Obj_IsDeleted(bossObj)){
ObjMove_SetPosition(GetPlayerObjectID,GetPlayerX+cos(GetAngleToPlayer(bossObj)+180),GetPlayerY+sin(GetAngleToPlayer(bossObj)+180));
wait(2) //wait(1) might also work
}
}
while(!Obj_IsDeleted(bossObj)) {
x = GetPlayerX;
y = GetPlayerY;
dir = GetPointToPointAngle(GetEnemyX, GetEnemyY, GetPlayerX, GetPlayerY);
ObjMove_SetAngle(locPlayerID, dir);
vx = v * cos(dir);
vy = v * sin(dir);
ObjRender_SetPosition(locPlayerID, x + vx, y + vy, 0);
yield;
}
I'm trying to make bullets that bounce off the wall once and then go throught players position (boss shoots at the wall, bullet reflects to the position player was at the moment that bullet was shot) but I'm having trouble calculating the initial angle for the bullet. Can anyone help with this?Store the player's X and Y position at the moment the bullet is fired, when it hits the wall calculate the angle between the bullet and said position: let angle= atan2(Y2-Y1,X2-X1); X2 and Y2 being the player's stored position, X1 and Y1 the bullet's current position.
ObjSprite2D_SetDestCenter(objEnemy);
ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 8);
Hi,
Is there a way to change the length of a loose laser while it is moving, such that it becomes shorter?
The thing is I'm setting the hitbox position just after setting the sprite position :Yes, but I'm saying that your sprite shouldn't be centered at (0, 0) of the whole window under normal circumstances. The most common reason you'd have this is if you were drawing the enemy at a render priority considered outside the bounds of gameplay, i.e. outside the range 20~80.Code: [Select]ObjSprite2D_SetDestCenter(objEnemy);
ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 8);
Both functions use a different referential and i don't get why it is actually the case.
Maybe I'm using the wrong function to set it up. The radius has an effect ?
There's ObjLaser_SetLength (https://dmf.shrinemaiden.org/wiki/Shot_Object_Functions#ObjLaser_SetLength) but you'll need to experiment a bit since I think it will shrink from the tip towards the base.
Yes, but I'm saying that your sprite shouldn't be centered at (0, 0) of the whole window under normal circumstances. The most common reason you'd have this is if you were drawing the enemy at a render priority considered outside the bounds of gameplay, i.e. outside the range 20~80.
task TStage
{
let dir = GetCurrentScriptDirectory();
let path = dir ~ "Stage 1/Plural_midBoss.dnh";
let idScript = LoadScriptInThread(path);
.
. my stage
.
StartScript(idScript);
while(!IsCloseScript(idScript) && GetPlayerState() != STATE_END)
{
yield;
}
.
. my stage again
.
CloseStgScene();
}
Thinking about the spinning straight lasers, I wonder if there's a code that the rotation of a spinning laser is decelerated to 0 (like Yuyuko lasers during the final spell: https://youtu.be/PuU9Rxi_vyY?t=8) before it fires... If there's one solution, then let me know.
ObjMove_SetPosition(obj, ObjMove_GetX(BossObj)+r*cos(ang),ObjMove_GetY(BossObj)+r*sin(ang),ang);
ObjStLaser_SetAngle(obj, numofhowmanylasertobespined);
How can I make difficulties like Easy, Normal, Hard and Lunatic? (without having to make 4 plurals, since it takes too much space and time?)
How can I make difficulties like Easy, Normal, Hard and Lunatic? (without having to make 4 plurals, since it takes too much space and time?)
Hi, how can I do the humming sound when hitting a boss?
Basically you have a task that constantly creates coloured copies of the boss sprite and then enlarges their scale and lowers their alpha, deleting them when the alpha lowers below zero. You might need to mess around with blend types a little to make the aura look nice.Wouldn't it cause some good amount of lag?
Wouldn't it cause some good amount of lag?
And which function can I use to make the alpha of the boss texture white? (I mean to make the boss all white, but with the opacity)
I recommend taking a render target of the boss, and applying a shader that sets every pixel to your desired color while maintaining the alpha channel valueHow can I do that?(I don't know about neither shaders nor render targets)
How can I increase playing field's size using camera zoom without changing STG frame?Not sure if this is possible. There is no "zoom out" for 2D cam afaik.
How can I increase playing field's size using camera zoom without changing STG frame?
Not sure if this is possible. There is no "zoom out" for 2D cam afaik.While it is possible to zoom in and out using Set2DCameraRatio (https://dmf.shrinemaiden.org/wiki/2D_Camera_Functions#Set2DCameraRatio) (or using Set2DCameraRatioX or Set2DCameraRatioY), it doesn't affect the playing field (I think you'd have to use SetStgFrame (https://dmf.shrinemaiden.org/wiki/System_Functions#SetStgFrame) somehow). Haven't been able to figure it quite out, but I'm sure it's there somewhere.
So, I'm trying to implement a continue system. I made a menu appear after pleyer's last life, and after pressing "continue" the game continues, player gets 3 additional lives, but still doesn't revive. It seems that player's state is still at STATE_END and doesn't change even after gaining new lives. What can I do?
case(EV_PLAYER_SHOOTDOWN){ //To disable continue system, block comment this case.
if(GetPlayerLife < 0){ //If equals 0, still have a life left (IE using last life)
SetPlayerLife(0.123); //Copied from Arby, should prevent STATE_END.
ContinueSystem;
}
}
Hm, I never thought you can use anything but integers in life value. Thanks for the help
How can I receive x and y coordinates of the laser's end?
Can someone provide me with a working example of replaye save scene? I tried using the default one without any changes, but after I enter the name of replay and press "done"(or whatever this means 終了) error on the first picture appears. Than I tried to change the default script a bit, and I end up with error on second picture and I don't even know what it means. After some manual change in texts that appear, I managed to surpass that problem (just kinda. I made it go away, but the intended result is also unreachable that way), but the first one still appears after that. Here is my replay save script, which is almost fully copied default version https://pastebin.com/nZBKDhAM
I'm getting some kind of error code on the log window when I try to output calculated values:
#INF00 for a number
#IND00 for a different number
#QNAN0 for a trigonometric function that essentially takes the sum of the above numbers
What do these warning mean, and what is likely the problem?
Thanks in advance
Please provide the code you are using, the actual error, and more context.
I'm getting some kind of error code on the log window when I try to output calculated values:
1.#INF00 for a number
-1.#IND00 for a different number
1.#QNAN0 for a trigonometric function that essentially takes the sum of the above numbers
What do these warnings mean, and what is likely the problem?
Okay, I'll remember that next time
Thank you, I'll try to add a limit onto the angular acceleration.
while(!boolean){yield;}
, I'd write WaitUntil(boolean);
.
task a(){
let bool = false;
function WaitUntilFlag(){
while(!bool){ yield; }
}
task b(){
// stuff
bool = true;
}
b();
WaitUntilFlag();
// finish
}
I'm trying to render a Mitori to a script, but when I mirror the scale/angle, the sprite bugs.
https://pastebin.com/tvn4KtZR(code)
I'm trying to replicate a spell card (for practice purposes) and all is going well until:A quick glance show me a missing semi-colon:
https://imgur.com/D69b2Za (https://imgur.com/D69b2Za)
...I need a curly bracket? After a wait?
And even if I do add it, it just springs to another problem (movement not defined, CenterX() something, etc.).
Normally I'd just think I messed up since I'm still a coding newbie, but every code I made beforehand worked fine. The only difference between this and previous codes is what the bullets are doing.
Can an extra set of eyes help me out? I'm honestly stumped at this point.
Full code: https://pastebin.com/aKH9vHMH (https://pastebin.com/aKH9vHMH)
A quick glance show me a missing semi-colon:
ObjMove_SetDestAtFrame(objBoss, GetCenterX(), 112, 60);
The laser generated by the following code appears to have no hitbox detection.
Can somebody please explain to me what's going wrong?
[code>]
laserObj = CreateStraightLaserA1(xPos,yPos,aim,512,5,5,graphic,0);
ObjShot_SetIntersectionEnable(laserObj,true);
If you check the documentation (https://dmf.shrinemaiden.org/wiki/Shot_Functions#CreateStraightLaserA1), then you'll see that the sixth parameter is how many frames that the laser exists for before disappearing. You've set that to 5, which means your laser exists for a fraction of a second before disappearing, which isn't enough time for it to impact anything. I also really suggest moving the delay and length up to at least 30 and 20 respectively.
A few questions about the HUD Frame and System files:
- What I need to use to make a Highscore gimmick?
- How can I make one? Or are there any scripts for research?
- Should I use a image or Danmakufu's text funcs? (EX: Score, Lives, Difficulty, etc)
- Help with the Player's Hearts and Stars?
- Should I use ZUN's HUD rips or try to make a new one?
4: Depends on what you mean. What kind of system do you want (Life/Bomb fragments? Fairies of Sorcery style? Fairy Wars style?)
Hi!
I'm completely new to Danmakufu, but I've been keeping up with a lot of tutorials from both Helepolis and Sparen when it comes to making scripts.
However, I have had trouble looking for any resources concerning player scripts and I'm left completely in the dust when it comes to this. The one big question I have for this is:
How can I create the little options/familiars that are present with the player? Like Reimu's yin-yang orbs or Marisa's lasers.
task TFire (loopNum, speed, angle, shotID, delay) {
let hx;
let hy;
loop (loopNum) {
hx = (13 * cos(angle)) - (5 * cos(2 * angle)) - (2 * cos(3 * angle)) - cos(4 * angle);
hy = 16 * sin(angle)^3;
CreateShotA1(bossX + (2 * hx), bossY + (2 * hy), speed, angle, shotID, delay);
angle += 360/loopNum;
}
}
i'm now trying parametric equations with my danmaku to make a heart but my issue is that the heart only spawns in one direction regardless of angle
is there any way i can fix this to change the direction the heart is pointing? its always pointing at a 180 degree angle
task phantomPrism{
//loop and speed is set weird to make sure it's shaped correctly
let angleT = 90;
PlaySE(charge);
BFX_Charge(ObjMove_GetX(objBoss),ObjMove_GetY(objBoss),150,60);
wait(60);
loop(500){
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;}
let obj = CreateShotA1(ObjMove_GetX(objBoss) + (2*cos(angleT) + cos(angleT*2)), ObjMove_GetY(objBoss) + (2*sin(angleT) - sin(angleT*2)), 0, angleT, 204, 0);
angleT += 360/60;
yield;
}
//ObjMove_SetDestAtFrame(objBoss, rand(GetCenterX -120, GetCenterX + 120), rand(GetCenterY - 100, GetCenterY - 170), 60);
}
Code: [Select]let obj = CreateShotA1(ObjMove_GetX(objBoss) + (2*cos(angleT) + cos(angleT*2)), ObjMove_GetY(objBoss) + (2*sin(angleT) + sin(angleT*2)), 0, angleT, 204, 0);
x = a(2cos(t) + cos(2t)), y = a(2sin(t) - sin(2t))
In your y component you're doing 2sin(t) + sin(2t) instead of 2sin(t) - sin(2t)?
Actually saw that earlier and tried that, but it still spirals. Just spawns a little differently.
Now why I didn't put that in when I pasted it here idek. I'll update that.
Even took a leap and changed the first + in the y into a - also, but its still spiraling.
I know trig is a tricky section, but it's still kinda weird.
Polar form: r = a sin(kθ)
Cartesian form: (x^2+ y^2)^3 = 4 a^2x^2y^2
Polar form: r = a sin(kθ)
Cartesian form: (x^2+ y^2)^3 = 4 a^2x^2y^2
task Rhodonea{
let t = 0;
let numflowers = 5;
let radius = 128;
while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0) {
loop(5) {
let effectiverad = radius * sin(numflowers * t);
let obj = CreateShotA1(ObjMove_GetX(objBoss) + effectiverad*cos(t), ObjMove_GetY(objBoss) + effectiverad*sin(t), 0, 0, DS_BALL_BS_SKY, 10);
Obj_DeleteAtFrame(obj, 120);
t += 360/5;
}
t += 0.5;
yield;
}
}
I copy-pasted your code in Danmakufu, multiplied the x and y components by 64 so that you can see the pattern, and it's working perfectly.Oh wow! Thanks. T̶h̶o̶u̶g̶h̶ ̶I̶ ̶k̶i̶n̶d̶a̶ ̶d̶o̶n̶'̶t̶ ̶u̶n̶d̶e̶r̶s̶t̶a̶n̶d̶ ̶w̶h̶y̶ ̶a̶ ̶6̶4̶ ̶w̶a̶s̶ ̶n̶e̶e̶d̶e̶d̶ ̶i̶n̶ ̶t̶h̶e̶ ̶f̶i̶r̶s̶t̶ ̶p̶l̶a̶c̶e̶.̶.̶.̶ ̶d̶a̶n̶m̶a̶k̶u̶f̶u̶ ̶t̶h̶i̶n̶g̶s̶,̶ ̶I̶ ̶g̶u̶e̶s̶s̶?̶ Nevermind I figured that out. It's for size. There's my error's origin then :V
Hello, everyone. I'm trying to implement a replay system, but this error on the picture always pops up when i finish writing the name. I use default replay script as the base. It resulted in the same error even before I reworked it. What could be the issue?
Hi, i have a problem with my code, the sprite is just not showing up. Its a 32 by 32 sprite.You're setting the scale of the image to 0,0,0. Take a look at line #89. The scale is set specifically to zero when speed is equal to 0 or when the boss is "moving". No idea why you're doing this.
https://pastebin.com/gaVzrub0
Image:
https://imgur.com/a/iK7RJXK
the sprite's a 32 x 32
Please help me take a look at it.
Hello, everyone. I'm trying to implement a replay system, but this error on the picture always pops up when i finish writing the name. I use default replay script as the base. It resulted in the same error even before I reworked it. What could be the issue?
Here's replay scirpt (https://pastebin.com/W8fUSVC1) and part of the package (https://pastebin.com/mQ3SNdtE) I call it in. Hope, that's enought
How do you create beams of the type that are seen in the Extra of Great Fairy Wars?
So far, I have tried using lasers, but they are very bright, and are bullet-shaped. I would ideally prefer something in a cone or triangular shape.
if you actually want to look at the mess, here you go https://pastebin.com/sAHLmt8J (https://pastebin.com/sAHLmt8J)This seems more or less fine for something simple. What is the current problem? Are you only running the script once at the start of a stage, or are you starting it on every pattern? That would be my guess as to why things are getting brighter.
This seems more or less fine for something simple. What is the current problem? Are you only running the script once at the start of a stage, or are you starting it on every pattern? That would be my guess as to why things are getting brighter.I forgot to specify (will I ever learn :V) that this scripts problem is the effect not showing up (in this case, the fog.)for the basic(nonspell?) background. That's on my end, sorry.
Surprise, it is ;Phahahaha :V
In the nonspell part you imply that if a spell is active, make those objects visible, rather than invisible. The moon is showing up because you never wrote a line for Obj_SetVisible(obj2, alpha > 0) so it isn't being set to invisible to begin with.
let frame = 0;
loop {
Obj_SetVisible(obj1, !bSpell); // Visible only when spell not active
Obj_SetVisible(obj2, !bSpell); // Visible only when spell not active
ObjSprite2D_SetSourceRect(obj1, 0, 0 + (frame*2) % -512, -512, -512 + (frame*2) % -512);
frame++;
yield;
}
stuffAh, I see. I was just confusing myself then. Thank you!
You could probably make it work with lasers if you turned their alpha down and made cones or triangles out of a bunch of small lasers. Probably not the most efficient method though.
I use Windows 10, and Danmakfu's window is really weird. When the window is expanded, the actual game covers only a portion of the window; the rest is just gray space. When not expanded, only part of the game is visible, meaning I can only really play with the former. The config program doesn't work, either. I can't close the program in any way but shutting it down with Task Manager. Is this a problem with Windows 10 in general, or is it specific to how I'm using Danmakufu? (For the record, I do not have AppLocale. I have no idea if these problems are all connected to me not having it.)
Danmakufu 0.12m or ph3?Dang it, I forgot to mention my version. It's ph3. Here's some photos of what the window looks like in both sizes.
If it's ph3, the window size is fixed, but it should run regardless of locale.
If it's 0.12m, you MUST use Japanese Locale to avoid a crash.
Are you attempting to fullscreen the window or something? It may also help to provide a screenshot so that we can better understand your problem.
I've attached a config file with default settings, can you plop this in your folder and see if this changes anything? Also, can you describe what you mean by the config.exe not working?I can change the window style settings in config.exe just fine, but I can't change the screen refresh rate to 1/2 or back to 1/1, if I change it to 1/3 or Flexible. The close, Start Game, OK, and Cancel buttons don't do anything when I click on them. The Exit command located in the File(F) button in the taskbar does nothing, either, even when I press Alt + F4. In addition, despite the window style being set to a window, the window size section is completely blank.
Forgive me, but I've never used this function before, and I'm not completely clear on what it's doing from the documentation alone.
Is it creating a pointer with a character ID?
It also seems to be suggested that I may have to clean up after finishing with the 'key' by using Obj_DeleteValue(), is this correct?
Object Values are like extra attributes.
Obj_SetValue(obj, "New_Field", <value>) uses the integer Object ID to locate the object instance, then adds the attribute "New_Field" to the instance. The type of "New_Field" is defined to be the type of the value.
Note that the attribute is local to the instance of the object. When the object is deleted, all its attributes are deleted as well.
I would not use the term pointer in this case since Danmakufu doesn't have Pass By Reference at all.
Um... So it's defining a type?
How exactly is this used to reference obj from a task?
And is this different from the what would be returned by making a variable '= obj' ?
Danmakufu doesn't require explicit type declarations.
As long as you have an object ID, you can access the object from any location as long as it has not been deleted.
Object IDs can be passed as parameters to a task or function.
I don't quite understand what you mean by '= obj'.
let obj = Obj*_Create();
Obj_SetValue(obj, "field", value);
let x = Obj_GetValue(obj, "field"); //-> x = value
let obj = Obj*_Create();
Obj_SetValue(obj, "shots", shot_array);
Task1(obj);
Task2(obj);
task Task1(){
let local_shot_array = Obj_GetValue(obj, "shots");
// modify local_shot_array
Obj_SetValue(obj, "shots", local_shot_array);
}
task Task2(){
let local_shot_array = Obj_GetValue(obj, "shots");
// modify local_shot_array
Obj_SetValue(obj, "shots", local_shot_array);
}
let shot_array = bla;
Task1();
Task2();
task Task1(){
// access shot_array directly
}
task Task2(){
// access shot_array directly
}
So as I put an opening bracket in the save replay, this error pops up.
Is there anything than can help? Let me know if there's one.
Please Respond! :wat: Thank you.
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjRender_SetBlendType(obj,BLEND_ADD_RGB);
Obj_SetRenderPriority(obj, 1);
ObjPrim_SetTexture(obj,GetCurrentScriptDirectory()~"brokenheart.png");
ObjSprite2D_SetSourceRect(obj,0,0,20,16);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetPosition(obj,floor(x),floor(y),1);
The image I'm trying to render is 20x16. Rendering a 16x16 image this way works perfectly - the image appears very crisp: (https://i.postimg.cc/3JFPcBsB/Untitled.png). Any ideas?
I'm trying to render a simple sprite in Danmakufu ph3, but am having problems. Trying to render this sprite: (https://i.postimg.cc/s2qPckKN/brokenheart.png) gives me this: (https://i.postimg.cc/sgS3xSqG/Untitled.png), with this code run every frame:Code: [Select]let obj = ObjPrim_Create(OBJ_SPRITE_2D);
The image I'm trying to render is 20x16. Rendering a 16x16 image this way works perfectly - the image appears very crisp: (https://i.postimg.cc/3JFPcBsB/Untitled.png). Any ideas?
ObjRender_SetBlendType(obj,BLEND_ADD_RGB);
Obj_SetRenderPriority(obj, 1);
ObjPrim_SetTexture(obj,GetCurrentScriptDirectory()~"brokenheart.png");
ObjSprite2D_SetSourceRect(obj,0,0,20,16);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetPosition(obj,floor(x),floor(y),1);
The image is still blurry, however: (https://i.postimg.cc/x1Gf8FvN/Untitled.png).
let objPlayer = GetPlayerObjectID();
task RenderPlayer(){
ObjRender_SetBlendType(objPlayer, BLEND_ADD_ARGB);
ObjPrim_SetTexture(objPlayer, GetCurrentScriptDirectory() ~ "brokenheart.png");
ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 20, 16);
ObjSprite2D_SetDestCenter(objPlayer);
}
How would I go about removing the default boss health bar?
I can't just set the texture to the player because decimal coordinates cause the image to be blurry. I tried flooring the player's position every frame, but that ended up causing movement problems. Rendering the image as its own sprite with floored coordinates works. I used a new sprite every frame because it gave me more control over rendering, but I think a continuous task would be more concise.Ah you already got to that; I was going to save that for the next step because I figured you'd have an issue with that. It's done pretty much as you think it is:
task DrawHeart(){
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
ObjPrim_SetTexture(obj, dir~"brokenheart.png");
ObjSprite2D_SetSourceRect(obj, 0, 0, 20, 16);
ObjSprite2D_SetDestCenter(obj);
while(!Obj_IsDeleted(objPlayer)){
ObjRender_SetPosition(obj, floor(ObjMove_GetX(objPlayer)), floor(ObjMove_GetY(objPlayer)), 0);
yield;
}
}
let obj = ObjPrim_Create(OBJ_SPRITE_LIST_2D);
ObjPrim_SetTexture(obj, dir~"enm_test.png");
ObjSpriteList2D_SetSourceRect(obj, 0, 0, 32, 32);
ObjSpriteList2D_SetDestCenter(obj);
ascent(i in 0..10){
ObjRender_SetPosition(obj, 100+i*20, 100+i*20, 0);
ObjRender_SetAngleZ(obj, i*36);
ObjSpriteList2D_AddVertex(obj);
}
case(EV_PLAYER_SHOOTDOWN) {
pichuunHandler;
PlaySFX(SFX_PLDEAD01);
DeleteShotAllEX(TYPE_SHOT,TYPE_IMMEDIATE,GetPlayerX,GetPlayerY);
}
case(EV_PLAYER_REBIRTH) {
SetPlayerSpell(2);
SetPlayerInvincibilityFrame(240);
invincEffect(240);
SetForbidPlayerShot(false);
SetForbidPlayerSpell(false);
}
I take it that this means that EV_PLAYER_SHOOTDOWN is the one that is only called after the player is actually dead then?If you want to be really sure, output a debug text on screen and modify the value inside EV_HIT and EV_PLAYER_SHOOTDOWN and EV_PLAYER_REBIRTH. Counterbomb when hit and monitor what the value becomes. Then you will see/understand the flow of "pichuun"
I'll use that in this case.
task TPlural {
let obj = ObjEnemyBossScene_Create();
//Singles added to boss scene here...
ObjEnemyBossScene_LoadInThread(obj);
ObjEnemyBossScene_Regist(obj);
while(!Obj_IsDeleted(obj)){
yield;
}
//Execution never reaches this point
CloseScript(GetOwnScriptID());
}
let index = SearchChar(Text, 0, '\');
function SearchChar(Text, startindex, Char)
{
let index = -1;
ascent(i in startindex..length(Text))
{
if(Text[i] == Char){index = i;break;}
}
return index;
}
I want to display the filepath of a script but Windows uses '\' instead of '/' and they are displayed as ? instead of '\'.
Is there a easy way to retrieve the position of a '\' within a string so i can replace it with a '/'?
I know that '\' is the escape character. So code like below returns an error.
"The length of a character type value is only 1"Code: [Select]let index = SearchChar(Text, 0, '\');
function SearchChar(Text, startindex, Char)
{
let index = -1;
ascent(i in startindex..length(Text))
{
if(Text[i] == Char){index = i;break;}
}
return index;
}
let index = SearchChar(Text, 0, '\\');
"\\ "[0]
function replace(str, a, b){
ascent(i in 0..length(str)){
if(str[i] == a){
str[i] = b;
}
}
return str;
}
let fixedpath = replace(path, "\\ "[0], '/');
let path = GetSomeKindOfPath(); // returns "C:\Users\Name\Desktop\"
ascent(i in 0..length(path){
if(path[i]+0 == 92){
path[i] = '/';
}
}
print(path); // => "C:/Users/Name/Desktop/"
Where is the ideal place to put the code for dialogue before a boss battle?
Should it be part of the stage script, plural, attached to the first single script, or in a single of its own?
Same question applies to post-battle dialogue, in the event that the answers are different.
Thanks in advance
SetForbidPlayerShot(true);
SetForbidPlayerSpell(true);
and the spell's lasers are gone. The things that happens are Darken Screen and the Sound Effect of my player's bomb are visible, but lasers are missing.If you have SetForbidPlayerSpell set, you can't trigger EV_REQUEST_SPELL, so your bomb will not activate. It's structured correctly.
SetForbidPlayerShot(true);
What can I do in this case? Or how could do that bomb in other way?
The lasers are also player shots, so if you forbid player shots they will not fire. Why are you trying to forbid player shots? Do you just want to stop the player from firing while the spell card is active?
If this is what you want, you can add if(!IsPlayerSpellActive()) as a condition to fire your main player shots. You should also add some kind of wait before you delete the spell manager object, since that's the signal to say the spell is finished.Is that so easy to do? (sorry I'm new in creating player scripts, I want create MY OWN PLAYER SCRIPTS in order to quit using the player scripts that others made, I'm not comfortable using scripts that aren't mine)
Is that so easy to do? (sorry I'm new in creating player scripts, I want create MY OWN PLAYER SCRIPTS in order to quit using the player scripts that others made, I'm not comfortable using scripts that aren't mine)If that is the case, then it is highly suggested to read and follow tutorials so you will be making your own player scripts.
If that is the case, then it is highly suggested to read and follow tutorials so you will be making your own player scripts.Where I search that tutorials? I need to improve my skills in creating player scripts! :D :D :D :D
while(!Obj_IsDeleted(ID))
{
if(!IsPlayerSpellActive){
if(GetVirtualKeyState(VK_SHOT) == KEY_PUSH||[...]
[...]
}
wait(5);
}
task Bloody_Laser(frame, num, amnt)
{
[...]
// loop firing lasers
OSCURECER_PANTALLA(GetPlayerX(), GetPlayerY(), 40, [50, 110, 255], 405);
Blink;
Obj_Delete(man);
}
task Bloody_Laser(frame, num, amnt)
{
[...]
// loop firing lasers
OSCURECER_PANTALLA(GetPlayerX(), GetPlayerY(), 40, [50, 110, 255], 405);
Blink;
wait(300);
Obj_Delete(man);
}
SetForbidPlayerShot(true);
I've noticed that when a text object inserts a line break in a string due to it hitting max length, the line break can be added in the middle of a word. Is there a way to stop this behaviour, short of manually specifying all line breaks?
Basically the Spell Card is about many blue and red bullets that go towards the upper part of the screenHave you tried using "ObjMove_AddPatternA3"? You can use it to change the bullets' angle, speed, etc., and the bullet graphic.(in a "Geyser style")and when they reach a random section of the upper part they are supposed to aim at the player (or a random section where the player is) as if there was no gravity and with a different graphic. I've been able to recreate the first part of the Spell, but I really can't get past the second one.
//Shooting bullet(s), assuming they're defined to an object called "bullet"
//. . .
TBulletChange(bullet);
//. . .
task TBulletChange(obj){
if(ObjMove_GetY(obj) == 60){
ObjMove_AddPatternA3(obj, rand(25, 60), NO_CHANGE, GetAngletoPlayer(obj), NO_CHANGE, NO_CHANGE, ObjMove_GetSpeed(obj), "Bullet graphic ID you want to change into");
}
}
And I doubt it's the easiest way to do it, I just do it like this myself.And sorry for my bad English!Ah shush, your English isn't bad. ^-^
Have you tried using "ObjMove_AddPatternA3"? You can use it to change the bullets' angle, speed, etc., and the bullet graphic.
If you want to change their direction in a random section on the upper part, you can try to make the code that's going to change the bullets' way/graphic get executed when they reach a certain y coordinate (for example 60), and make the code wait for random time (for example 20-60 frames).
AKA something like this:Code: [Select]//Shooting bullet(s), assuming they're defined to an object called "bullet"
And I doubt it's the easiest way to do it, I just do it like this myself.Ah shush, your English isn't bad. ^-^
//. . .
TBulletChange(bullet);
//. . .
task TBulletChange(obj){
if(ObjMove_GetY(obj) == 60){
ObjMove_AddPatternA3(obj, rand(25, 60), NO_CHANGE, GetAngletoPlayer(obj), NO_CHANGE, NO_CHANGE, ObjMove_GetSpeed(obj), "Bullet graphic ID you want to change into");
}
}
Note: If you're using CreateShotB2 to create bullets, the code above wouldn't work, and you need to find a different way to make bullets face to the player, which I don't know, sorry.
Additionally, CommonDataArea can be saved to a file and thus become "persistent" data. CommonData is cleared once the game ends. Useful if you want to store progress (spellcard history etc.) / configuration settings and such of a player
- Write a script that creates a CommonData with a key value pair and save it with empty string value as you wrote.
- Also write somewhere where the commondata is loaded and the data is read.
- Close the script/game
- Reboot game and see what happens.[/li][/list]
Do report your findings, I would say
Hi Guys! I need to do a gravity bullet vortex, how I could do that? :smokedcheese:
Please describe what a gravity bullet vortex is first :)
task TStage
{
wait(60);
StartScript(idScriptA);SetAreaCommonData("System", "BossInspiration", r[3]);
while(!IsCloseScript(idScriptA)) //Run plural-stg00e-mid.dnh - midboss event
{
yield;
}
StartScript(idScriptB);SetAreaCommonData("System", "BossInspiration", r[3]);
while(!IsCloseScript(idScriptB)) //Run plural-stg00e-talk.dnh - the dialogue event
{
yield;
}
wait(240);
CloseStgScene();
}
let g_obj_boss; //This is the variable to set to Enemy Boss in scripts.
@Initialize{
SetShotAutoDeleteClip(480,480,480,480);
g_obj_boss = ObjEnemy_Create(OBJ_ENEMY_BOSS); //The object as an Enemy Boss
ObjEnemy_Regist(g_obj_boss);
//Init_Boss_Aura(g_obj_boss,32,176,255,32,64,255,1);
Render_Boss_Anim(g_obj_boss,anim_HBKT);ObjEnemy_SetDamageRate(g_obj_boss, 0, 0);
ObjMove_SetDestAtFrame(g_obj_boss, trunc(GetCenterX()+rand(-96,96)), trunc((GetCenterY()/2)+rand(-16,16)), 30); //The coordinates of the Boss Object
StartSpell;
init_phase1;
TFinalize;
}
@Initialize{
g_obj_boss = ObjEnemy_Create(OBJ_ENEMY); //The object as an enemy during the dialogue. Still a boss.
ObjEnemy_Regist(g_obj_boss);
//Init_Boss_Aura(g_obj_boss,32,176,255,32,64,255,1);
ObjMove_SetDestAtFrame(g_obj_boss, trunc(GetCenterX()), trunc((GetCenterY()/2)+rand(-16,16)), 60); //The coordinates of the enemy object after the boss dies before the event dialogue.
Render_Boss_Anim(g_obj_boss,anim_Hika);ObjEnemy_SetDamageRate(g_obj_boss, 0, 0);
SetCommonData("event_dialogue",true);
SetShotAutoDeleteClip(480,480,480,480);
SetTalk;
CheckEventDia;
}
@MainLoop{
yield;
}
//Create Anything, heheh.
task SetTalk
{
wait(90);
DrawBorder;
SetText_Simple(chartype[1],charcolor_ubkt[0],charcolor_ubkt[1],charcolor_ubkt[2],"My...");
SetText_Simple(chartype[1],charcolor_ubkt[0],charcolor_ubkt[1],charcolor_ubkt[2],"I've been hardly noticed...");
SetText_Simple(chartype[0],charcolor_nemuno[0],charcolor_nemuno[1],charcolor_nemuno[2],"Well, not a bad problem.");
... ... ...
...
}
So I tried creating my own simple dialogue system like the touhou games from 6-11.
As I put my variable 'g_obj_boss' for local format, as follows:
Stage part:
-At Plural Script 1, I set the boss variable to an object enemy boss.
when the boss health reaches to 0, the boss's position automatically sets to 0-0 coordinates as it proceeds to the next plural part (the Dialogue) where I created the variable boss as enemy.
-After the dialogue, the boss object's position automatically resets to 0-0 coordinates as it proceeds to the next plural part (the boss part). Still I'm running out of time before New Year...
Anyone can help explain this if you watch it and read it. Please Respond. ty.
It is difficult to understand what your question/your problem is just by reading your description. Consider reading https://stackoverflow.com/help/mcve (https://stackoverflow.com/help/mcve). tl;dr you haven't explained what your problem is, haven't stated what you actually *want* to happen, and haven't produced enough context/code to tell where each component is being called.
Assuming that your issue is that the boss position is not being maintained between consecutive scripts:
Ensure that communication between scripts is being done via Common Data. Setting the position of an enemy you will delete and recreate will not be sufficient for setting a position between different scripts. Refer to https://sparen.github.io/ph3tutorials/ph3u3l24.html (https://sparen.github.io/ph3tutorials/ph3u3l24.html)
Assuming that your issue is confusion between Boss Enemy Objects and Boss Scene Objects:
Refer to https://sparen.github.io/ph3tutorials/ph3u2l12.html (https://sparen.github.io/ph3tutorials/ph3u2l12.html) and https://sparen.github.io/ph3tutorials/ph3u3l23.html (https://sparen.github.io/ph3tutorials/ph3u3l23.html)
task TStage
{
wait(60);
StartScript(idScriptA);SetAreaCommonData("System", "BossInspiration", r[3]);
while(!IsCloseScript(idScriptA)) //Run plural-stg00e-mid.dnh - midboss event
{
yield;
}
StartScript(idScriptB);SetAreaCommonData("System", "BossInspiration", r[3]);
while(!IsCloseScript(idScriptB)) //Run plural-stg00e-talk.dnh - the dialogue event
{
yield;
}
wait(240);
CloseStgScene();
}
let g_obj_boss; //This is the variable to set to Enemy Boss in scripts.
@Initialize{
SetShotAutoDeleteClip(480,480,480,480);
g_obj_boss = ObjEnemy_Create(OBJ_ENEMY_BOSS); //The object as an Enemy Boss
ObjEnemy_Regist(g_obj_boss);
//Init_Boss_Aura(g_obj_boss,32,176,255,32,64,255,1);
Render_Boss_Anim(g_obj_boss,anim_HBKT);ObjEnemy_SetDamageRate(g_obj_boss, 0, 0);
ObjMove_SetDestAtFrame(g_obj_boss, trunc(GetCenterX()+rand(-96,96)), trunc((GetCenterY()/2)+rand(-16,16)), 30); //The coordinates of the Boss Object
StartSpell;
init_phase1;
TFinalize;
}
@Initialize{
g_obj_boss = ObjEnemy_Create(OBJ_ENEMY); //The object as an enemy during the dialogue. Still a boss.
ObjEnemy_Regist(g_obj_boss);
//Init_Boss_Aura(g_obj_boss,32,176,255,32,64,255,1);
ObjMove_SetDestAtFrame(g_obj_boss, trunc(GetCenterX()), trunc((GetCenterY()/2)+rand(-16,16)), 60); //The coordinates of the enemy object after the boss dies before the event dialogue.
Render_Boss_Anim(g_obj_boss,anim_Hika);ObjEnemy_SetDamageRate(g_obj_boss, 0, 0);
SetCommonData("event_dialogue",true);
SetShotAutoDeleteClip(480,480,480,480);
SetTalk;
CheckEventDia;
}
@MainLoop{
yield;
}
//Create Anything, heheh.
task SetTalk
{
wait(90);
DrawBorder;
SetText_Simple(chartype[1],charcolor_ubkt[0],charcolor_ubkt[1],charcolor_ubkt[2],"My...");
SetText_Simple(chartype[1],charcolor_ubkt[0],charcolor_ubkt[1],charcolor_ubkt[2],"I've been hardly noticed...");
SetText_Simple(chartype[0],charcolor_nemuno[0],charcolor_nemuno[1],charcolor_nemuno[2],"Well, not a bad problem.");
... ... ...
...
}
//This code goes on @MainLoop
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0)
{
Obj_Delete(objBoss);
DeleteShotAll(TYPE_ALL, TYPE_IMMEDIATE));
SetAutoDeleteObject(true);
CloseScript(GetOwnScriptID());
return;
}
I'm with a little doubt, I'm having this problem with the function DeleteShotAll() in @MainLoop (I'm following Sparen's ph3 Tutorial):You're closing DeleteShotAll with two parentheses.Code: [Select]//This code goes on @MainLoop
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0)
{
Obj_Delete(objBoss);
DeleteShotAll(TYPE_ALL, TYPE_IMMEDIATE));
SetAutoDeleteObject(true);
CloseScript(GetOwnScriptID());
return;
}
When I run this, Danmakufu gives me an error message saying it should have a "}" at the DeleteShotAll() line. But why? If I comment the entire DeleteShotAll() line, it runs with no error, so it's no brace matching mistake. Also when I use the task method. I thought this was some property of the function, but it doesn't make any sense.
You're closing DeleteShotAll with two parentheses.
Oh... that explains it. God, that was awful, I was so precautious about the braces I forgot completely of the parenthesis -_- I hope nobody would commit this kind of error.While the actual error description is vague and could come over as misleading, the line number usually tells the truth. There are a few rare conditions I ran into where the line number would trick the reader.
I see that some scripts use .txt files and some use .dnh files.
Is there a difference, other than personal preference?
Is it possible to vary the alpha value of a laser along its length?
Hmm... I have a question.
What's the purpose of a loading system (when you open a pre-packaged danmakufu script)?
Can you describe the loading system? I wanted to know for sure, thank you.
What do you mean by 'loading system'?
task lazertime{
let i = 1;
loop{
loop(6){
let obj = CreateCurveLaserA1(ObjMove_GetX(Zataihou), ObjMove_GetY(Zataihou), 5, 120+i*10, 50, 20, 1019, 10); //shoots lasers. "Zataihou" would equal "objBoss" in this code, it itself being a name for an original character of mine. Yes, I'm weird.
i++;
} //if this brace is taken out, the lasers fire sequentially instead of at the same time. If it's in, Danmakufu shows "obj is not defined" error due to the "let souls" line.
loop(20){
wait(1);
let souls = CreateShotA1(ObjMove_GetX(obj),ObjMove_GetY(obj),0,0,294,10);} //would handle spawning of soul bullets along the lasers. No angle and speed set yet for testing. 294 is a Yuyuko-type, blue "butterfly" bullet graphic.
ObjCrLaser_SetTipDecrement(obj,0); //makes laser hitbox fair by removing their invisible parts
ObjMove_SetAngularVelocity(obj,-1); //curves the lasers
yield;}
The problem is : I'm unable to find a solution to fire all six lasers and have the trails appear at the same time. I have tried using different variations of loops, ascents, different positioning of curly braces, yields, to no avail. In the recent versions of the code idea, either the lasers appear one after the other, and the rest don't appear until the prior one finishes trailing, or I get a "variable is not defined" error.
Here is the most recent version of the code I've been experimenting with. No other shooting tasks run alongside this one, this task is included in Initialize. I didn't include movement commands for the soul-bullets in this one yet. I'm using the AllStar shotsheet in this example.Code: [Select]task lazertime{
let i = 1;
loop{
loop(6){
let obj = CreateCurveLaserA1(ObjMove_GetX(Zataihou), ObjMove_GetY(Zataihou), 5, 120+i*10, 50, 20, 1019, 10); //shoots lasers. "Zataihou" would equal "objBoss" in this code, it itself being a name for an original character of mine. Yes, I'm weird.
i++;
} //if this brace is taken out, the lasers fire sequentially instead of at the same time. If it's in, Danmakufu shows "obj is not defined" error due to the "let souls" line.
loop(20){
wait(1);
let souls = CreateShotA1(ObjMove_GetX(obj),ObjMove_GetY(obj),0,0,294,10);} //would handle spawning of soul bullets along the lasers. No angle and speed set yet for testing. 294 is a Yuyuko-type, blue "butterfly" bullet graphic.
ObjCrLaser_SetTipDecrement(obj,0); //makes laser hitbox fair by removing their invisible parts
ObjMove_SetAngularVelocity(obj,-1); //curves the lasers
yield;}
I've been thinking of making the trailing be handled by a seperate task, but it would likely also bring up a "variable is not defined" error. I've also seen people use arguments in task names, but I don't exactly get what is that used for, or how to make use of it. Any advice regarding these matters is greatly appreciated.
Tasks are the perfect solution to your problem, since you want each laser to perform the same task. In this case, you get the ID of each laser, and pass it to a task. In the task, the trails are made.
In other words, your code structure would be as follows:
In lazertime:
- In a loop without waiting (unless you want a delay between lasers), create your lasers, and call a new task, passing the laser ID as a parameter.
- In the new task, handle the trail.
Tasks run parallel to the main routine as long as you are using yield; in your Main Loop.
You shouldn't add angular velocity to non-curvy lasers. I've never been able to figure out how danmakufu's curvy lasers are supposed to work, so I just made my own out of a bunch of small straight lasers.
let angle = 0;
CreateShotA1(GetCenterX(),GetCenterY(),1,angle,5,5);
{
let angle = 90;
CreateShotA1(GetCenterX(),GetCenterY(),1,angle,5,5);
}
Hey, Sparen. It's been a great honor to be helped out by one of the grandfathers of Danmakufu, so to say.:V :V :V :V :V
Something went wrong, though, as bullets from the trail keep spawning at 0,0, even if if/while statements checking for if the parent lasers are deleted are included (and if they are deleted, remove said shots, but some still manage to spawn in 0,0 anyway). Perhaps due to them being spawned via an ascent?
task lazertime{
let angle = 100;
wait(60); //One time wait so the cutin can disappear by this time, and the boss can move into position
loop{
while(GetShotCount(Zataihou) > 160){yield;} //If there's many souls on screen, stop creating new lasers and trails. Once again, Zataihou = objBoss in this example.
wait(10);
ascent(i in 1..6){
let obj = CreateCurveLaserA1(ObjMove_GetX(Zataihou), ObjMove_GetY(Zataihou), 12, angle+i*12, 30, 20, 1019, 10); //Handles the lasers
ObjCrLaser_SetTipDecrement(obj,0); //Makes laser hitbox fair
ObjMove_SetAngularVelocity(obj,-7); //Handles the initial curving of the lasers
trail(obj); //Task to spawn trails
straighten(obj); //Task to have the lasers go straight after a short while (so they leave the screen)
angle+=30; //Increment angle to give different laser angles
}
}}
task trail(obj){
while(Obj_IsDeleted(obj)){return;} //Supposed to handle preventing 0,0 spawning, which works until player death, but some souls spawn at 0,0 anyway on respawn.
loop(5){
wait(8);
let souls = CreateShotA1(ObjMove_GetX(obj),ObjMove_GetY(obj),0,0,rand(291,298),10); //Creates the souls
fly(souls);} //Task to wait until there's a certain amount of souls, then let them begin moving
}
task straighten(obj){
ObjMove_AddPatternA2(obj,60,NO_CHANGE,NO_CHANGE,NO_CHANGE,0,11); //Task to straighten the lasers by setting their angular velocity to 0, leaving everything else intact.
}
task fly(souls){
while(GetShotCount(Zataihou) < 150){yield;} //Wait until there's enough souls, then...
ObjMove_AddPatternA2(souls,60,NO_CHANGE,rand(40,150),0.01,0,12); //... let them move around.
// As long as the obj IS NOT deleted, executed the code in between. Otherwise, jump over it (thus not executed)
while (!Obj_IsDeleted(obj)) {
// Spawn fancy trail stuff here.
}
You can translate the above code into human language but reading it out loud: "While the object is not deleted, execute the code in between which is CreateShotA etc.task fireCurvyLaser() {
// While the boss IS alive AND the number of shots IS BELOW 160, execute the code.
while (!Obj_IsDeleted(Zataihou) && GetShotCount(Zataihou) < 160) {
let obj = CreateCurveLaserA1(...);
// ... laser related stuff etc
spawnLaserTrail(obj);
wait(10);
}
}
task spawnLaserTrail(obj) {
// Loop 5x, but keep checking each loop whether the obj (laser) is NOT deleted. If the laser is "alive", spawn a soul (createShotA1)
loop(5) {
if (!Obj_IsDeleted(obj)) {
let soul = CreateShotA1(...);
}
wait(8);
}
}
task trail(obj){
while(!Obj_IsDeleted(obj)){ //Supposed to handle preventing 0,0 spawning
loop(5){
wait(8);
let souls = CreateShotA1(ObjMove_GetX(obj),ObjMove_GetY(obj),0,0,rand(291,298),10); //Creates the souls
fly(souls);} //Task to wait until there's a certain amount of souls, then let them begin moving
}}
if(GetPlayerState == STATE_DOWN){
DeleteShotAll(TYPE_ALL, TYPE_FADE);
task example{
loop{
ascent(i in 1..10){
let obj = any create shot function(arguments);
}
ObjMove_AddPatternA2(obj,stuff)
}
-I've been experimenting on a spellcard which spawns bullets in triangles randomly around the screen, which worked out well. However, I've been also thinking of a spell which would have bullets incoming from the edges of the screen as a part of it (rather than randomly spawn bullets anywhere on the screen, having them spawn along the edges only). What could be a possible way to implement it? Certainly not rand with values of STGFrame width and height, as it could spawn them anywhere, rather than at the edges only.Assuming that you want to utilize the edges of the screen exclusively, you can lock one coordinate and then set the other to be random along the edge.
Similiarly, how it would be best to create a task that begins spawning bullets from 0,0, then begins "going around" the screen, by going to the maximum x value, then the maximum y value, and so on, spawning bullets as it goes?
-If there are multiple objects spawning multiple objects of the same type sequentially (for example, big bullets labelled as obj, spawning smaller bullets declared as obj2), would the AddPattern function control each bullet (obj2 ones) at the same time, or in a certain order? I think it's the latter from experimenting with a spellcard in which lasers leave bullet trails, but I haven't confirmed it for sure.AddPattern applies to the object ID you pass to it. The frame you pass as a parameter is what controls the timing of the effect.
-There have been occasions of needing to use an ascent loop inside a loop (mainly for more complex patterns to use the i in the ascent as incrementing values, mainly the angle) for patterns. For example:Code: [Select]task example{
loop{
ascent(i in 1..10){
let obj = any create shot function(arguments);
}
ObjMove_AddPatternA2(obj,stuff)
}
However, in this case, an error about a non-declared variable would come up in the AddPattern line. I know it's due to the variable being inside the ascent loop, but I can't seem to find a workaround for it. Is there any?
Hey there, and thanks for the detailed reply, Sparen! The mentioned information is most definitely very helpful, espicially the part on solving the problem with variables. Despite having such a simple solution, I likely couldn't have figured it out my own. A bit embarrassing, I know.
Thanks once again!
Thanks, that video is helpful.No, that is also explained in this video tutorial (https://www.youtube.com/watch?v=jVkIiewpijE).
However, it makes me wonder, if I were to move the camera to an angle, does that mean I would have to recalculate the angles of the all the objects on the screen to control their positions?
/***********************
************************/
I discovered that adding this code causes danmakufu to not detect a .dnh script in its menu.Code: [Select]
/***********************
************************/
What causes this behaviour? Is "/***" or "***" or "***/" reserved syntax or something?
If the #TouhouDanmakufu is commented out, then the script will not appear in the Danmakufu menu. I assume this is what you have done (placed #TouhouDanmakufu within the block quotes).
It's a common technique to hide Single scripts you don't want cluttering up the Danmakufu menu + scripts that should not be executed by the player
I understand this, but this is not what happened. The comment block was midway down the script. Specifically, I was rewriting a piece of code that had been simulating a beam using a laser, this instead using a primitive object.
In other words, the comment itself was 'empty'. Above the comment was my new function (half-written at this point), and below the comment was the old function, which was no longer called in @Initialize.
Please provide your full code. It may be a different issue altogether (e.g. unrecognized symbol at a weird location, smart quotes, etc)
while(ObjEnemy_GetInfo(objBoss,INFO_LIFE) > 5000){yield};
Weird. I have absolutely no idea why Danmakufu doesn't like /**. Well, we have the source code, I guess.
Relevant code?
Parser for comments: https://github.com/UltimaOmega/TouhouDanmakufuRemastered/blob/master/source/GcLib/gstd/Script.cpp#L395
Danmakufu Header parsing: https://github.com/UltimaOmega/TouhouDanmakufuRemastered/blob/master/source/TouhouDanmakufu/Common/DnhCommon.cpp#L26
How could I tell Danmakufu to keep waiting until either the boss reaches certain life thresholds (activating each phase sequentially) or as it reaches a certain time (activate all phases at once)?
while(ObjEnemy_GetInfo(objBoss,INFO_LIFE) > 5000 || ObjEnemyBossScene_GetInfo(sceneObj,INFO_TIMER) < threshold){yield};
-For a plural script, how could I end a single (for example, a spell) and move on to the next attack (for example, a nonspell) in a way so the boss starts out where it was on the previous attack (rather than always teleporting into the starting position)?
-Is there a way to keep track of how many spell cards the player has successfully captured so far? (I'd like to implement a last spell that can only be encountered if x spells have been captured throughout the run).
Thanks for the reply, Arcvasti! Obviously, regarding the "have the boss start out where it was on the previous attack", I wanted to do that since it looks really wonky to have it teleport back to its original starting position every time an attack is cleared (unless it can be done in a simpler way by not deleting the boss after every attack, of course).
Thanks for the reply, Sparen! I wasn't in the know that that was actually the case, but after some testing, it indeed is! The issue was that I had included ObjMove_SetPosition (to half the STGFrameX and Y/4) in every Single that was in the Plural, which resulted in the boss being moved to that position every time for the new attack. Removing that piece of code resolved this issue.
Thanks once again!
Thanks for the reply, Sparen! I wasn't in the know that that was actually the case, but after some testing, it indeed is! The issue was that I had included ObjMove_SetPosition (to half the STGFrameX and Y/4) in every Single that was in the Plural, which resulted in the boss being moved to that position every time for the new attack. Removing that piece of code resolved this issue.
Thanks once again!
Hi everyone. I already asked the question here, but didn't get the answer, so I just forgot about it. Now though, I stumbled upon this problem one again, and really need to fix it. So, I'm trying to create a package but I'm having issues with saving replays. At the end of the process, the error on the immage appears. I tried using both custom replay saving scripts and the default one, but it's always the same. I also tried manually setting the SaveReplay parameters, but that doesn't work eather. And at that, I'm all out of ideas on how to fix it, so I need help.
task lazertime{
let angle = 100;
wait(60); //One time wait so the cutin can disappear by this time, and the boss can move into position
loop{
while(GetShotCount(Zataihou) > 160){yield;} //If there's many souls on screen, stop creating new lasers and trails. Souls are "Yuyuko-type butterflies".
wait(10);
ascent(i in 1..6){
let obj = CreateCurveLaserA1(ObjMove_GetX(Zataihou), ObjMove_GetY(Zataihou), 12, angle+i*12, 30, 20, 1019+i, 10); //Handles the lasers
SE_Play(laser2,70); //laser sound
ObjCrLaser_SetTipDecrement(obj,0); //Makes laser hitbox fair
ObjMove_SetAngularVelocity(obj,-7); //Handles the curving of the lasers
trail(obj); //Task to spawn trails. No issue with this one.
straighten(obj); //Task to have the lasers go straight after a short while (so they leave the screen). No issue here either.
angle+=30; //Increment angle to give different laser angles
}
}}
task fly(souls){
while(GetShotCount(Zataihou) < 150){yield;} //Wait until there's enough souls, then...
ObjMove_AddPatternA2(souls,60,NO_CHANGE,rand(40,150),0.01,0,12); //... let them move around.
SE_Play(charge4,100); //charge sound
}
task SE_Play(let path, let vl){
let seobj = ObjSound_Create;
ObjSound_Load(seobj,path);
ObjSound_Play(seobj);
ObjSound_SetVolumeRate(seobj,vl);
loop(120){yield;}
RemoveSound(path);
}
Please provide context sufficient enough for us to replicate your issue.Package part (https://pastebin.com/D6w07TBN), Continue (https://pastebin.com/Vu4JVpT7) script and ReplaySave (http://ReplaySave) script. The replay script is almost untouched, because i figured it has the main issue. As for replicating the problem, I don't really know how to do it, since I started making the package a while ago, and it has too many scripts connected with it. One thing I noticed tho, is that replayIndex in SaveReplay is somehow incorrect, but I don't know what's wrong with it
There are a couple problems with this kind of approach. The main issue you have is because the purpose of RemoveSound is to unload the file from memory. If you play a sound once and then try to play it again but the file is unloaded halfway through it'll just stop. It isn't the laser sound interacting with the charge sound, it's the several tasks calling RemoveSound all the time. The laser sounds are also going to be reset after 12 loops (i.e. 120 frames) but you probably won't notice it.Code: [Select]task SE_Play(let path, let vl){
let seobj = ObjSound_Create;
ObjSound_Load(seobj,path);
ObjSound_Play(seobj);
ObjSound_SetVolumeRate(seobj,vl);
loop(120){yield;}
RemoveSound(path);
}
Could the problem be that both sounds are being handled via SE_Play? What could be possible ways to fix this?
function SE_Play(path){
ObjSound_Play(SE_GetSoundObject(path));
}
function SE_GetSoundObject(path){
let se_table = GetCommonData("SE_TABLE", ID_INVALID);
if(se_table == ID_INVALID){
se_table = ObjSound_Create();
SetCommonData("SE_TABLE", se_table);
}
if(!Obj_IsValueExists(se_table, path)){
let obj = ObjSound_Create();
ObjSound_Load(obj, path);
Obj_SetValue(se_table, path, obj);
return obj;
}
return Obj_GetValueD(se_table, path, ID_INVALID);
}
let obj=ObjEnemyBossScene_Create();
ObjEnemyBossScene_Add(obj,0,CSD~"samplenonspell.txt"); //Naturally, these are not the names of the attacks, I just renamed it to this for the sake of simplicity.
ObjEnemyBossScene_Add(obj,0,CSD~"samplespell.txt");
. //the rest of the attacks here, which I didn't include to avoid a huge wall.
.
.
ObjEnemyBossScene_Add(obj,10,CSD~"finalspell.txt");
ObjEnemyBossScene_LoadInThread(obj);
ObjEnemyBossScene_Regist(obj);
while(!Obj_IsDeleted(obj))
{
yield;
}
BGMstop; //task to stop BGM after all attacks are done.
CloseScript(GetOwnScriptID());}
Are you able to vary things like blend types and alpha values between different vertices in a 2D Sprite List?This is the second post you've written in a row where you seem to already know what's happening and can clearly test things yourself but still want an explanation. If I don't answer this, how will you be able to figure this out? I honestly think you have the capacity to think about this on your own and I don't quite know why you're even asking. If I were teaching a Danmakufu course and you were a student, I would be asking you how to explain this.
Assuming the answer is yes, the follow up is; how do these blend/alpha types interact with each other and the environment once you call ObjSpriteList2D_CloseVertex() ?
For example, what would be the final alpha values for Vertex 1 and Vertex 2 after this type of code?
How do these blend types also interact with each other, especially if different vertices overlap with each other?
Thanks in advance.
One idea I've been thinking of is using a new variable in the form of obj2 in ObjEnemyBossScene_Create and the rest of the Boss Scene commands to handle the creation of a seperate lifebar, but I'm not sure if wait() would work in this case to handle the delay (I'm thinking the lack of a boss for a short while could cause the fight to prematurely end?).Try it.
This is the second post you've written in a row where you seem to already know what's happening and can clearly test things yourself but still want an explanation. If I don't answer this, how will you be able to figure this out? I honestly think you have the capacity to think about this on your own and I don't quite know why you're even asking. If I were teaching a Danmakufu course and you were a student, I would be asking you how to explain this.
* snip *If your goal is to purely analyse, experiment and theorize on the possibilities of Danmakufu functions and its source code then you're pretty much in bad luck. Until now, most of your posts come over as experiments and theory followed by conducting the test. My personal question: For what purpose/goal?
Mathematically if you have a pixel color value p1 with alpha a1 on top of a pixel color value p2, the result is (p1 * a1 + p2 * a2 * (1 - a1)). The resulting alpha is (a1 + a2 * (1 - a1)) which is just 1 if p2 is opaque. (Also these are normalized to 0~1 instead of 255 so the math looks nice)That you so much! I see where I went wrong now.
So like in your example, with two pixels with 0.5 alpha (or 128) you get a resulting alpha value of 0.5 + 0.5*(1-0.5) = 0.75, or 192 denormalized.
My advice would be to stop bothering or breaking your mind too much about these complex things. But if that makes you happy about Danmakufu then that is all fine. But please do keep in mind the purpose of this forum section.
Hi! I just wanted to ask how I could create a custom life system, specifically a system with life pieces, like SA or UFO. I understand the answer is probably too complex, so I'd be okay with just knowing the general idea behind it, or like, what aspects of danmakufu should I have no problems with before I attempt to code said system.
Also, I haven't been able to find any tutorial on the matter, but if you know one, I'd be happy with just that!
In general, you will need to utilize CommonData to store information on the life pieces, as well as custom items to support them.
Unfortunately this is a relatively advanced topic. For reference:
https://sparen.github.io/ph3tutorials/ph3u3l24.html (CommonData)
https://sparen.github.io/ph3tutorials/ph3u3l25.html (Events)
https://sparen.github.io/ph3tutorials/ph3u3l26.html (User Events)
https://sparen.github.io/ph3tutorials/ph3u3l27.html (Items)
basicbul(100, 100); //Calls the "absorption" bullet and it's x/y coordinates.
task basicbul(xa, ya){
CreateShotA1( xa, ya, 0, GetAngleToPlayer(objBoss), 20, 15); //Absorption bullet's creation
undefinedFantasticObject(xa, ya); //calls for the bullets being absorbed
}
task undefinedFantasticObject(xa, ya){
let xb = 300; //creates the x/y values for the aborbed bullets
let yb = 100;
let UFO = CreateShotA1( xb, yb, 2, 180, 3, 15);//creates said bullets
if(xa && ya == xb && yb){
Obj_Delete(UFO); //boolean that says "If bullet a's x/y values are the same as bullet b's x/y values, delete bullet b. *What's not working*
}
}
basicbul(100, 100); //Calls the "absorption" bullet and it's x/y coordinates.
task basicbul(xa, ya){
let absorber = CreateShotA1( xa, ya, 0, GetAngleToPlayer(objBoss), 20, 15);
undefinedFantasticObject(absorber); //calls for the bullets being absorbed
}
task undefinedFantasticObject(absorber){
let UFO = CreateShotA1(300, 100, 2, 180, 3, 15);
if(ObjMove_GetX(absorber) == ObjMove_GetX(UFO) && ObjMove_GetY(absorber) == ObjMove_GetY(UFO)){
Obj_Delete(UFO);
}
}
That way of phrasing the position check is incorrect. You want (xa == xb && ya == yb).
Also, xa, ya, xb, yb are just numbers. They aren't going to be updated with the bullet's new positions just because you spawned a bullet at those coordinates. Instead you need to work with the bullet objects you're creating. The ObjMove_GetX/Y functions are what will give you a bullet's current position.
Oh uh yes. I'm dumb and didn't put it in. Should wrap the collision check in while(!Obj_IsDeleted(absorber) && !Obj_IsDeleted(UFO)) and toss a yield in there. That way it checks every frame.
let x = rand(200,200); //works
let x = rand(200,201); //doesn't work, despite the probability that 50% of the bullets should be deleted.
// 0.12m personal transition for rand_int.
function rand_int(min,max) {
let rand_int_result;
rand_int_result = truncate(rand(min,max));
return rand_int_result;
}
It never once occurred to me decimals would be involved... :V:V hehehe
and for some reason every time I play it in the final main boss part the stage is literally consuming the FPS from 60 to 40, from 40 to 30, from 30 to 18 or less...
And how do I get a Log Windows?Open config.exe, go to Options and check Show Log Window. Then on launch the log window will appear, and you can check the Info tab for various things.
Ok, so I was trying to implement it into my spell and I have a question. Does randomness mess with the boolean? In the spell, the bullets come from different, randomized angles, yet eventually reach the center of the bullet, so it shouldn't be a big deal.This goes back to what I said about "this will probably have its own problem". This happens because collisions are more complicated than just position = position. Like Hele says, you could have a position value that is like 200.583921, and that will not be equal to 200. Even if a bullet gets close to the position of the other, the chances they will actually be equal is extremely small unless both bullets are tightly controlled (which is what you saw when you had no randomness and a 180 angle and integer-valued speed).
Interesting..., apparently what seems to keep increasing but without being erased is the obj_count like more than 7000, but I don't really know how to actually decrease or erase all of that... :ohdear: ??? :wat:Can you locate which objects are not deleting? Are they a bunch of bullets that go out of screan frame then move to infinty? Are they primitives for various effect that doesn't get deleted? There are a lot of things that could be causing this.
What do I do? Is it inside the script and needs a task or function for this or I'll need some kinda special file? :ohdear: ???
Or erase stuff? :wat:
task someComplexBullet() {
let obj = ...
while (!Obj_IsDeleted) {
// complex behaviour
if () {
Obj_Delete(obj);
}
}
}
Basically this task creates an object and is doing things while it is not deleted. This could be anything. You need to decide, as a programmer, when this object should be deleted. In the code example I did it with a if-statement, but it could be anything. The goal is to delete the object.Objects (effects, bullets etc) created by you are never auto-deleted. Even if they leave the screen.
What's the purpose of creating a bullet pattern that goes in a 3D geometric shape- Maybe because the author felt like it.
#include "./functions.dnh"
#include "./shotfunctions.dnh"
#include "./soundfunctions.dnh"
task shoot{
let count = 0;
loop{
if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && count%2 == 0){
if(CanShoot && !IsPlayerSpellActive){
//Regular shots
PlaySoundA1(9, 70, 0);
TShotRegular(GetPlayerX + 8, GetPlayerY, 20, 270, 1, damage*1.5);
TShotRegular(GetPlayerX - 8, GetPlayerY, 20, 270, 1, damage*1.5);
}
}
count++;
yield;
}
}
task option(rads, rads2, starta, aplus){
let objOption = ObjPrim_Create(OBJ_SPRITE_2D);
Obj_SetRenderPriorityI(objOption, 31);
ObjRender_SetBlendType(objOption, BLEND_ALPHA);
ObjPrim_SetTexture(objOption, GetCurrentScriptDirectory ~ "./....shot.png");
ObjSprite2D_SetSourceRect(objOption, 40, 45, 61, 67);
ObjSprite2D_SetDestCenter(objOption);
ObjRender_SetPosition(objOption, GetPlayerX, GetPlayerY, 0);
let destX;
let destY;
let dist;
let dir;
let a = starta;
let count = 0;
let shotAngle = -90;
while(!Obj_IsDeleted(objOption)){
if(!optionAlive){Obj_Delete(objOption);}
if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){
destX = GetPlayerX + rads[0]*cos(a);
destY = GetPlayerY + rads[1]*sin(a);
}else{
destX = GetPlayerX + rads2[0]*cos(a);
destY = GetPlayerY - 32 + rads2[1]*sin(a);
}
let opX = ObjRender_GetX(objOption);
let opY = ObjRender_GetY(objOption);
dist = GetDist(opX, opY, destX, destY);
dir = GetAngle(opX, opY, destX, destY);
opX += 0.25 * dist * cos(dir);
opY += 0.25 * dist * sin(dir);
ObjRender_SetPosition(objOption, opX, opY, 0);
ObjRender_SetAngleZ(objOption, count * 2);
if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && count%2 == 0){
if(CanShoot && !IsPlayerSpellActive){
PlaySoundA1(6, 60, 0);
if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){
TShotRegular(opX, opY, 20, 270, 3, damage*1.5);
TShotRegular(opX, opY, 10, 270, 3, damage*1.5);
}else{
TShotRegular(opX, opY, 20, 270, 3, damage*2.5);
TShotRegular(opX, opY, 20, 270, 3, damage*2.5);
}
}
}
count++;
a += aplus;
yield;
}
}
If I am not mistaking, rand() uses the entered parameter as a float and not an integer. What happens under the hood is that if you enter 200 as a parameter, it is actually initialized as 200.000000 by the engine.
If you use rand(200,201) the engine will actually generate a random number between 200.00000 and 201.000000. So technically the randomized number could be 200.583921. So there is no 50% :V Awesome aint it?
To solve this in my own game, I've created my own rand_int() function (which used to exist in 0.12m). It is actually quite dirty because it truncates the decimal value. Pretty sure someone else has a better suggestion to this.Code: [Select]// 0.12m personal transition for rand_int.
function rand_int(min,max) {
let rand_int_result;
rand_int_result = truncate(rand(min,max));
return rand_int_result;
}
function rand_int(low,high) {
return truncate(rand(low,high+1));
}
rand() is inclusive on lower and upper bounds, so you can still technically get 201 there. Anyways, the truncate method screws up if you use negative numbers: with your method rand_int(-1, 0) basically always returns 0, and rand_int(-2, -1) has the same problem of almost never returning -2 while also returning 0 half the time which is very wrong.I didn't give the negative number case a thought yet, good point. I suppose what follows now is the better rand_int that I'll be using in my code.
function rand_int(low,high){
return round(rand(low-0.49999,high+0.49999));
}
But I don't understand very well, is it bad if I use Jan Aldryn Bio Fairy Functions or is it better if I do my own ???
After all I remember two or three people using this functions other than himself and they worked fine...
The first easy approach that comes to mind is to Monte Carlo it. The ice area doesn't need to be exact, and you can balance efficiency versus accuracy. Find the bounding box of the circles, throw a bunch of random points out and check against each circle. The ratio of the points hitting a circle to the total points multiplied by the area of the bounding box is approximately the covered area.I suppose that works well enough. After fiddling around a bit I found that trying max(100, min(1000, 1000 / (length(circles)/10)^0.5 ) ) points across the whole screen (too lazy to find a bounding box) seems to give a decent balance of efficiency and accuracy.
Blargel doesn't seem to be roaming IRC or forums any more. His last activity was February 2018. That is a year ago. I am afraid you won't be able to get something registered on bulletforge :ohdear:Bluh
You could use RenderToTexture over the STG frame then using that texture draw a primitive rectangle using the picture corner coordinates as UV vertices (instead of making a sprite like you're probably thinking).Hmm, I'll look into that. For now I got it working using the 2D camera settings and SaveSnapShotA2 - it's not rendering everything perfectly (some stuff in the background has too much alpha, see screenshot) but it seems good enough for now.
function take_pic(at_x, at_y, to_x, to_y, scale){
let x = at_x+GetStgFrameLeft();
let y = at_y+GetStgFrameTop();
let a = -20;
let w = 200;
let h = w/4*3;
let cam = [
// camera center + corner offsets + rotation
[x + (-w/2*cos(a) - h/2*sin(a)), y + (-w/2*sin(a) + h/2*cos(a))],
[x + ( w/2*cos(a) - h/2*sin(a)), y + ( w/2*sin(a) + h/2*cos(a))],
[x + (-w/2*cos(a) + h/2*sin(a)), y + (-w/2*sin(a) - h/2*cos(a))],
[x + ( w/2*cos(a) + h/2*sin(a)), y + ( w/2*sin(a) - h/2*cos(a))]
];
let pic_id = GetCommonData("CAMERA_PIC_COUNT", 0);
SetCommonData("CAMERA_PIC_COUNT", pic_id + 1);
let tex = "CAMERA_PIC_" ~ rtos("000", pic_id);
CreateRenderTarget(tex);
RenderToTextureA1(tex, 20, 60, true);
let p = ObjPrim_Create(OBJ_PRIMITIVE_2D);
ObjPrim_SetPrimitiveType(p, PRIMITIVE_TRIANGLESTRIP);
ObjPrim_SetVertexCount(p, 4);
ObjPrim_SetTexture(p, tex);
ascent(i in 0..4){
ObjPrim_SetVertexUVT(p, i, cam[i][0], cam[i][1]);
ObjPrim_SetVertexPosition(p, i, cam[i][0]-x, cam[i][1]-y, 0);
}
ObjRender_SetPosition(p, to_x, to_y, 0);
ObjRender_SetScaleXYZ(p, scale, scale, 1);
Obj_SetRenderPriorityI(p, 90);
}
if(!IsCommonDataAreaExists("cutin_History")){CreateCommonDataArea("cutin_History");}
LoadCommonDataAreaA1("cutin_History"); // <-- force quits here
I've commented out one of the two places I found this but it still happens; possibly a third place?let isconfig = LoadCommonDataAreaA2("CONFIG",dirdat~"config.dat");
if(!isconfig){
CreateCommonDataArea("CONFIG");
SetAreaCommonData("CONFIG","Difficulty",NORMAL);
SetAreaCommonData("CONFIG","MainEquip",EQ_CAMERA);
SaveCommonDataAreaA2("CONFIG",dirdat~"config.dat");
}
let path = dirdat~GetScriptInfoA1(GetMainStgScriptPath, INFO_SCRIPT_ID)~"_common_cutin_History.dat";
LoadCommonDataAreaA2("cutin_History",path);
but THIS doesn't:let path = dirdat~GetScriptInfoA1(GetMainStgScriptPath, INFO_SCRIPT_ID)~"_common_cutin_History_asdf.dat";
LoadCommonDataAreaA2("cutin_History",path);
I don't get itWhat are the contents of the data? Does it still crash if it's empty or has just one value stored? What's the minimal replicating conditions you can find?Here's the code where the contents are set (not mine):
//These are long-looking common data group names
let SpellDataAttempt = SpellName~"|"~CutinDifficulty~"|"~GetPlayerID~"|"~"Attempt";
let SpellDataGet = SpellName~"|"~CutinDifficulty~"|"~GetPlayerID~"|"~"Get";
//This is actually the common data retrieval
let SpellValueAttempt = GetAreaCommonData("cutin_History", SpellDataAttempt, 0);
let SpellValueGet = GetAreaCommonData("cutin_History", SpellDataGet, 0);
if(!IsReplay){
SpellValueAttempt++;
SetAreaCommonData("cutin_History", SpellDataAttempt, SpellValueAttempt);
SaveCommonDataAreaA1("cutin_History");
}
if(!IsCommonDataAreaExists("cutin_History")){CreateCommonDataArea("cutin_History");}
LoadCommonDataAreaA1("cutin_History");
let group = CurrentSC~"|"~GetCommonData("Difficulty","Normal")~"|"~GetPlayerID()~"|";
let hiscore = GetAreaCommonData("cutin_History", group~"DecisiveBestShot|Score", 10000);
if(photoScore > hiscore){
SetAreaCommonData("cutin_History",group~"DecisiveBestShot|Score", photoScore);
SetAreaCommonData("cutin_History",group~"DecisiveBestShot|Angle", origAngle);
SetAreaCommonData("cutin_History",group~"DecisiveBestShot|Boni", Obj_GetValueD(photo,"Boni",[])); // <----- wait... is it this?!?!?!
let _CurrentSC = JoinString(SplitString(CurrentSC,"\"/*|<>:? _"),""); //remove characters that can't be in filename
let fname = dirdat~"DecisiveBestShot_"~_CurrentSC~"_"~GetCommonData("Difficulty","Normal")~"_"~GetPlayerID~".png";
LoadTexture(texture); //this is ridiculous but I couldn't find a better way that was actually working
let obj = CreateSprite(0,0,texture,[0,0,GetTextureWidth(texture),GetTextureHeight(texture)], 99);
ObjSprite2D_SetDestRect(obj,0,0,GetTextureWidth(texture),GetTextureHeight(texture));
SaveSnapShotA2( fname, 0,0,GetTextureWidth(texture),GetTextureHeight(texture));
Obj_Delete(obj);
}
let photosTaken = GetAreaCommonData("cutin_History", group~"PhotosTaken", 0);
SetAreaCommonData("cutin_History",group~"PhotosTaken", photosTaken + GetCommonData("PhotosTaken",1));
SaveCommonDataAreaA1("cutin_History");
How would you recommend implementing a LoLK-style checkpoint system?
Oh, boy... Before I do answer this question, let me warn you, it is a huuuuge pain in the butt to do.
Oof, so I see.Ah, uh, if you're making a Spell Card Collection-style or StB/DS-style thing where there's just one attack per scene, then you don't really need anything Pointdevice-like...? Merely restarting everything without regard for what happened at any previous point in time would be totally fine I believe.
Honestly I'm mostly trying to do StB/DS-type stuff where the spell restarts if you take a hit. So I'm more than willing to abandon saving the whole state and just clear everything out and go back to the beginning.
Ah, uh, if you're making a Spell Card Collection-style or StB/DS-style thing where there's just one attack per scene, then you don't really need anything Pointdevice-like...? Merely restarting everything without regard for what happened at any previous point in time would be totally fine I believe.Well, yes. But cleaning everything up and restarting without actually reloading the script isn't trivial, either. When I tried to just have my main task return and call it again I was getting a bunch of weird lag. The way I have it now is essentially skipping to the bottom of the main task, spamming DeleteShotAll for a few frames, and resetting the score and graze, along with the boss' life/photos taken.
So I wound up reworking how I'm taking photos to use a primitive like what Drake posted, but I'm having a hard time getting clean edges when taking pics that overlap the edge of the stage frame. It's wrapping around and capturing stuff from the other side of the screen. My current workaround is drawing a sprite that covers up everything but the capture region, so any wraparound should in theory just be white, but it's having rather inconsistent results. Sometimes it works fine, other times it just doesn't block it at all, other times it blocks part of it but other parts get through. The parts getting through are always triangular, though may be cut off. (See attached screenshot for an example.)
Any suggestions for how to prevent this, or insight into how it might be happening?
I personally wouldn't rotate the image just to rotate it back again, though I might be totally derping out with my reading - if it turns out you didn't actually do so, then please ignore me lol.No no, that's exactly what I'm doing. It's because I want to save the decisive best shot for each scene but can only save a non-rotated rectangle.
So the idea is to keep a list of centers of your images and of the angles at which your viewfinder was tilted when the photo was taken.That is pretty much what I'm doing now, yes. Thing is, it's wrapping around weirdly and I don't know why.
So rendering that to an image, and then a white border on top of that, you'd have exactly what you'd see in the first image attached below.
I'd rather not render the entire image, so I use a primitive object with vertices placed where the corners of the viewfinder were located.
It seems you have something of a similar idea?
As for what I did to make my photos fade to transparency -That's pretty cool, I won't lie. I don't think it would solve my issue, though, since I'm only capturing layers that are inside the stage frame anyway.
I have a border covering the sidebar so that everything outside of the playing field is black, everything inside is white, and there's a sort of gradient in between just on the inside of the edge. I throw that into an alpha mask shader that interprets value/brightness as transparency. That way none of what's outside the playing screen is visible. See second image for an example.
I think it should work though. Applying a filter to a small image or a large image will do the same thing so don't worry about that. Save the one as a separate file or render target and apply it over your photo.Ah... Now I see what you're suggesting. I suppose I could try that. Though, for the moment I'm more likely to just throw a white primitive on top of the part of the photo I want to blank out.
For reference, here's an image (https://dl.dropboxusercontent.com/s/w4whjf1qsgrkoua/stg_borderfadeout.png) Chronojet used for applying to the STG frame as a transparency filter.
case(EV_GET_ITEM){
//statements;
}
In the player's @Event section, you can addCode: [Select]case(EV_GET_ITEM){
//statements;
}
and you can add sound effects in there since it will run every time the player gets an item
My player script go through a lag that freeze a few seconds Danmakufu and then, render a shield around the player (instead of using TMagicCircle()).
And when the player dies and keep pressing the shot button, this error happens:
https://ibb.co/GsgyB0C (https://ibb.co/GsgyB0C)
What can I do in these cases?
Player link: https://1drv.ms/u/s!AgwNeb6oBlvsgd9U5gYLfol-acAwmA (https://1drv.ms/u/s!AgwNeb6oBlvsgd9U5gYLfol-acAwmA)
I've noticed that I put this post outside of this thread, my apologies :P
I've removed your other thread, thanks for noticing and posting in the correct thread --Hele
while(!Obj_IsDeleted(Option)){
if(!yetAlive){
Obj_Delete(Option);
}
// stuff being run
yield;
}
How could I find the x and y position where a laser collides with the edges of the screen? I want to spawn some bullets on that point, but I can't figure out a way to obtain the coordinates...
Given a laser's starting point and angle, you're trying to find the laser's intersection with one of the edges with the screen. For each edge, you can obtain the perpendicular distance to the edge from the laser's origin using the x/y coordinates of the respective edge and the laser's origin. Then using trigonometry, you can determine the missing coordinate.
For example, the left side of the STG_Frame and the laser being spawned at (64, 128) at 120 degrees. The laser, the edge, and the perpendicular line from the laser origin to the edge form a right triangle, where the angle between the perpendicular line and the laser is 60 degrees. Using the definition of the tangent, we get that tan(60) = opp/adj where adj = 64. Therefore, opp = 64*tan(60) = 110.85. Adding the initial height of 128, we get 238.85.
Therefore, the laser meets the edge at (0, 238.85).
A similar method can be applied for the other edges.
Hi, doesn't really know if someone actually asked this but how to make a boss move towards the player in a set amount of time ? I've been testing all the time and it wasn't working for me.Depends on whether or not you want the boss to constantly adapt to the player's position or move to the location of the player at a certain time (regardless of where the player moves afterwards). Regardless, this stuff is in the tutorials. Refer to https://sparen.github.io/ph3tutorials/docs_object.html#sub14 for some hints.
Side request, how can I create a laser pillar ?What do you mean by a 'laser pillar'? If you mean a Straight Laser, then there are functions to create those. Otherwise, you'll need to be more specific as to what you are trying to create.
Well apparently I left out the GetPlayerX and Y, no wonder I can get it right... At least I successfully did it. Thank you so much !
About the laser side request, I want to try to script this in a straight and simple way and not by tasking it one by one.
Hi again, I was wondering how to let all/specified bullets stop on a certain time like Cirno in Perfect Freeze ?
task freeze(){
let flag = 0;
loop(180){
task bullet(){
// make bullet
while(!flag){ yield; }
// freeze
}
bullet();
yield;
}
loop(60){yield;}
flag = true;
}
So I try to experiment the code but it always gives out this error after a few seconds
A variable was changing it's value type. (File Line : 102)
And it always lagging for the whole period and the error appeared .
How can I fix it ? ???
https://pastebin.com/BpJff2d6
Can you help me? My system has a problem...I forgot delete
When the player reach to a certain nonspell, and a certain percentage of vitality comes down, the boss's steps and difficulty indicator are deleted for no apparent reason...
Obj_Delete(obj)
from my Fade In task, my apologies :V
ItemData{ id = 2 type = 2 rect = (192, 0, 208, 16) out = ( 194, 14, 205, 25) render = ALPHA }
When a normally-behaving item goes above the top of the screen there's a graphic shown that tells you the item is dropping there; in Touhou games it's a small triangular arrow. The `out` rect is for that graphic.
task BoWaP{
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0) {return;}
let angleT = rand(0, 360);
let objcount = 0;
loop{
loop(5){
let obj = CreateShotA1(ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 3, angleT, 52, 5);
angleT += 360/5;
}
angleT += sin(objcount) * cos(objcount) * 12;
objcount++;
yield;
}
}
When I run the code through the game it appears to stack the different patterns that the bullets are producing. Is there anything I have done wrong in the code that causes this?
So I'm new to danmakufu and touhou in general and I've been trying to recreate Border of Wave and Particle. I have this current code setup:Code: [Select]task BoWaP{
When I run the code through the game it appears to stack the different patterns that the bullets are producing. Is there anything I have done wrong in the code that causes this?
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0) {return;}
let angleT = rand(0, 360);
let objcount = 0;
loop{
loop(5){
let obj = CreateShotA1(ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 3, angleT, 52, 5);
angleT += 360/5;
}
angleT += sin(objcount) * cos(objcount) * 12;
objcount++;
yield;
}
}
@MainLoop{
ObjEnemy_SetIntersectionCircleToShot(bossObj, ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 32);
ObjEnemy_SetIntersectionCircleToPlayer(bossObj, ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 24);
if (count == 0) {
ObjMove_SetDestAtFrame(bossObj, GetCenterX(), 112, 60);
}
if(count % 30 == 0 && count >= 0){
BoWaP;
}
count++;
yield;
}
I was making the bullets to spawn bullets, it works, but the bullets also appeared on the top left of the screen.
How can I overcome this situation ?
https://pastebin.com/R82cpE05
I was making the bullets to spawn bullets, it works, but the bullets also appeared on the top left of the screen.
How can I overcome this situation ?
https://pastebin.com/R82cpE05
while(!Obj_IsDeleted(obj)){
//code here;
}
function rand_int(min, max){
return floor(rand(min, max));
}
alternative(rand_int(0, 22))
case(0){
RING_1();
wait(32 * 7 + 60);
}case(1){
RING_2();
wait(32 * 13);
}case(2){
// ...
}case(21){
Octo_Fist(fr);
wait(fr + 1340);
}
You would generate a random number and then pick based on that using a switch or a bunch of if-elses.Thanks Drake! It works! :3 :D
Hi! I doubt I'll get a response, but I thought it was worth a shotAlmost all your questions are covered in tutorials. Detailed written tutorials: https://sparen.github.io/ph3tutorials/ph3tutorials.html and video tutorials: https://www.shrinemaiden.org/forum/index.php?topic=2852.0
I'm new to Danmakufu stuff, and I wanna ask a couple questions:
How do I make it so the spellcard activates when the health is down to a certain point, like in Touhou?
How do I make more lives for the boss?
How do I create dialogue?
Sorry for 3 questions, but I'm just a baby to this stuff and I thought this would be the correct place to ask.
How to do a difficulty selector for plurals? Can you explain me? I want to do that with pictures instead of using only text ::)Depends on what your ultimate goal is. If it is just difficulty selection for plural (or single boss fight), then use:
if (frame%60==0)
{
let obj = ShotA(1); //ShotA is any createshot
}
ObjMove_SetX(obj, 0); //error: obj is not defined
Please post code along with the error because we don't know how you exactly programmed this.Code: [Select]if (frame%60==0)
{
let obj = ShotA(1); //ShotA is any createshot
}
ObjMove_SetX(obj, 0); //error: obj is not defined
And this throws an error. How can I use an variable out of its {}?
code: https://pastebin.com/Yx1NdbdJ (look for if (frame%30==0) )
-> How can I use an variable out of its declared {}?
loop(8)
{
let obj = CreateShotA1(rand(0,fx), 0, rand(1,3), 90+rand(-5,5), DS_BALL_BS_GREEN, 20);
}
ObjMove_SetAngle(obj, -90); // obj is not defined
Your aim is to create eight objects and then set their angle immediately. Therefore, you can do the following: loop(8)
{
let obj = CreateShotA1(rand(0,fx), 0, rand(1,3), 90+rand(-5,5), DS_BALL_BS_GREEN, 20);
ObjMove_SetAngle(obj, -90); // obj is not defined
}
task summonWolf(wx, wy)
{
let wa = atan2(GetPlayerY - wy, GetPlayerX - wx);
let ws = 6;
let wolf = CreateCurveLaserA1(wx, wy, ws, wa, 60, 30, DS_SCALE_WHITE, 0);
let wolf2 = CreateCurveLaserA1(wx, wy, ws, wa, 60, 30, DS_NEEDLE_WHITE, 0);
ObjCrLaser_SetTipDecrement(wolf, 0);
ObjCrLaser_SetTipDecrement(wolf2, 0);
let accel = 0.07;
let wvelo = 2;
ascent (i in 0..10)
{
ObjMove_AddPatternA2(wolf, 0 + 120 * i, NO_CHANGE, NO_CHANGE, -accel, 0, -1000);
ObjMove_AddPatternA2(wolf2, 0 + 120 * i, NO_CHANGE, NO_CHANGE, -accel, 0, -1000);
ObjMove_AddPatternA2(wolf, 60 + 120 * i, NO_CHANGE, NO_CHANGE, accel, 0, 1000);
ObjMove_AddPatternA2(wolf2, 60 + 120 * i, NO_CHANGE, NO_CHANGE, accel, 0, 1000);
}
//let objText = ObjText_Create();
//ObjText_SetText(objText, "--> Russell Square Regular <--");
loop(720)
{
let lx = ObjMove_GetX(wolf);
let ly = ObjMove_GetY(wolf);
let la = ObjMove_GetAngle(wolf) % 360;
let la2 = atan2(GetPlayerY - ly, GetPlayerX - lx);
//ObjText_SetText(objText, la2 - la);
if (la < la2)
{
ObjMove_SetAngularVelocity(wolf, wvelo);
ObjMove_SetAngularVelocity(wolf2, wvelo);
}
else
{
ObjMove_SetAngularVelocity(wolf, -wvelo);
ObjMove_SetAngularVelocity(wolf2, -wvelo);
}
yield;
}
}
task fire(angle, dir)
{
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;}
let dist = 100;
let bulNum = 10;
let time = 240;
let bx = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let by = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let bul = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let ang = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
ascent(i in 0..bulNum)
{
ang[i] = angle + dir * i * 360/bulNum;
bx[i] = dist * cos(ang[i]) + ObjMove_GetX(objBoss);
by[i] = dist * sin(ang[i]) + ObjMove_GetY(objBoss);
bul[i] = CreateShotA1(bx[i], by[i], 2, ang[i], DS_BALL_M_BLUE, 20);
}
loop(time)
{
ascent(i in 0..bulNum)
{
ang[i] = ang[i] + 2 * PHI;
ObjMove_SetPosition(bul[i], dist * cos(ang[i]) + ObjMove_GetX(objBoss), dist * sin(ang[i]) + ObjMove_GetY(objBoss));
ObjMove_SetAngle(bul[i], ang[i]);
}
yield;
}
}
ascent(i in 0..n) {
CreateRotatingObj(objBoss, i, n, r);
}
task CreateRotatingObj(parent, ID, numinring, radius) {
let offset = ID * 360/numinring;
let obj = CreateShotA1(ObjMove_GetX(parent) + radius*cos(offset), ObjMove_GetY(parent) + radius*sin(offset), 0, 0, 0, 0);
let objcount = 0;
while(!Obj_IsDeleted(parent)) {
ObjMove_SetX(obj, ObjMove_GetX(parent) + radius*cos(offset + objcount);
ObjMove_SetY(obj, ObjMove_GetY(parent) + radius*sin(offset + objcount);
objcount += 1;
yield;
}
Obj_Delete(obj);
}
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["Momiji Fight"]
#Text["for kiiro"]
@Event
{
}
@Initialize
{
TPlural;
}
@MainLoop
{
yield;
}
task TPlural
{
let dir = GetCurrentScriptDirectory();
let obj = ObjEnemyBossScene_Create();
ObjEnemyBossScene_Add(obj, 0, dir ~ "momiji 1.txt");
ObjEnemyBossScene_Add(obj, 0, dir ~ "momiji spell 1.txt");
ObjEnemyBossScene_Add(obj, 1, dir ~ "momiji 2.txt");
ObjEnemyBossScene_Add(obj, 1, dir ~ "momiji spell 2.txt");
ObjEnemyBossScene_Add(obj, 2, dir ~ "momiji 3.txt");
ObjEnemyBossScene_Add(obj, 2, dir ~ "momiji spell 3.txt");
ObjEnemyBossScene_Add(obj, 3, dir ~ "momiji spell 4.txt");
ObjEnemyBossScene_Add(obj, 4, dir ~ "momiji spell 5.txt");
ObjEnemyBossScene_LoadInThread(obj);
ObjEnemyBossScene_Regist(obj);
while(!Obj_IsDeleted(obj)){
yield;
}
CloseScript(GetOwnScriptID());
}
How to make a function so that the bullet is gradually increasing/decreasing the alpha ? Had no idea how it works, any help is appreciated.
function upAlpha(obj, seconds){
ascent(i in 0..256){
ObjRender_SetAlpha(obj, i);
wait(60*seconds);
}
}
function wait(n){loop(n){yield;}}
Hey there! I was just wondering how to make a player shoot bullets. I'm trying to make a player script and I can't for the life of me figure out how to go about doing that. Does anyone have tips to start off doing that at least?
shot_image = "./playershot.png" // image
ShotData {
id = 1
rect = (left,top,right,bottom)
render = ALPHA
alpha = x // 0-255
collision = y // radius of the hitbox
}
ShotData {
id = 2
...
let shots = dirCurrent ~ "player_shot.txt";
LoadPlayerShotData(shots);
Thank you for the advise! Quick question though do I implement it like this?
task TShoot(){
CreatePlayerShotA1(GetPlayerX(), GetPlayerY(), 3, 2, 10, 10, 1);
}
Oh gosh it's been a while but I'm genuinely stumped right now
I was wondering if someone could look through the script and see where I'm going wrong because I'm genuinely unsure of what to do right now
It's still not working and I'm not really sure if I'm going about this the wrong way so feel free to look through it
Thank you for the help though! I appreciate every single advise/tip~
The player shots don't really appear :/Ah, a classic mistake. Yea you got to love that strict variable name for the player bullet script :V I remember it took me several minutes of cursing when I had figured it out.
The sprite animation seems to be working just fine, it's just the shooting part that's not working
EDIT:
NVM my player shots seem to be working now! I just put in the wrong variable name in the player bullet script ^^;;
There are tutorials about that by both Sparen and me for making player scripts + spell bombs. Might want to check them out.
Don't know how to explain this, but I'll try to make it as clear as possible.
1. How to script a trail of straight laser based on random boss movement (rand(n,n)) ? [attach=1]
2. What to script so that the boss can automatically detects and runs into the center of the bullet no matter what position the boss is (directly piercing it) and the bullet will react (like explode etc) [attach=2]
I'm having problems rendering transparent images. A grey always appears at the edge of the pictures. Just look at this screenshot.
(https://i.imgur.com/RbzvfKp.png)
The mandala in the middle is a purely black transparent image put on top of the rest of the background, but where opaque meets transparent, the grey appears.
Please provide your code so that we can see your render priorities and blend types. Also provide the raw images so that we can see if there are any notable assumptions that were made when writing the code.
//The object containing the mandala
let BG = ObjPrim_Create(OBJ_SPRITE_LIST_2D);
ObjPrim_SetTexture(BG,current ~ "BG_Pattern.png");
Obj_SetRenderPriorityI(BG,3);
let BG_Glow = ObjPrim_Create(OBJ_SPRITE_LIST_2D);
ObjPrim_SetTexture(BG_Glow,current ~ "BG_Pattern.png");
Obj_SetRenderPriorityI(BG_Glow,3);
ObjRender_SetBlendType(BG_Glow,BLEND_ADD_RGB);
let BGangle = rand(0,45);
let BGphase = rand(0,360);
let BGalpha = 0;
yield;
Intro;
while(bSpell){
ObjSpriteList2D_ClearVertexCount(BG);
ObjSpriteList2D_SetSourceRect(BG,0,0,800,600);
ObjSpriteList2D_SetDestRect(BG,-320,-240,320,240);
ObjRender_SetAlpha(BG,255*BGalpha);
ObjRender_SetAngleZ(BG,0);
ObjRender_SetColor(BG,255,255,255);
ObjRender_SetPosition(BG,320,240,0);
ObjSpriteList2D_AddVertex(BG);
ObjSpriteList2D_SetSourceRect(BG,800,0,1600,600);
ObjSpriteList2D_SetDestRect(BG,-320,-240,320,240);
ObjRender_SetAlpha(BG,255*sin(BGphase/2)^2*BGalpha);
ObjRender_SetPosition(BG,320,240,0);
ObjSpriteList2D_AddVertex(BG);
//Creating the mandala
ObjSpriteList2D_SetSourceRect(BG,853,601,1278,1026);
ObjSpriteList2D_SetDestRect(BG,-213*0.8,-213*0.8,213*0.8,213*0.8);
ObjRender_SetAlpha(BG,255*BGalpha);
ObjRender_SetAngleZ(BG,BGangle);
ObjRender_SetPosition(BG,320,240,0);
ObjSpriteList2D_AddVertex(BG);
ObjSpriteList2D_CloseVertex(BG);
(https://i.imgur.com/1IpDkN3.png)
if(GetVirtualKeyState(VK_SLOWMOVE)==KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE)==KEY_HOLD){
ObjRender_SetPosition(extrashot, GetPlayerX-10, GetPlayerY-30, 3);
ObjRender_SetPosition(extrashot2, GetPlayerX+10, GetPlayerY-30, 3);
}
else{
ObjRender_SetPosition(extrashot, GetPlayerX-30, GetPlayerY-30, 3);
ObjRender_SetPosition(extrashot2, GetPlayerX+30, GetPlayerY-30, 3);
}
Hello! So I got back into doing Danmakufu again and I'm almost there with implementing something like Reimu's Yin Yang balls. I managed to have them move into a different position when I press the shift key but they teleport instead:Code: [Select]if(GetVirtualKeyState(VK_SLOWMOVE)==KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE)==KEY_HOLD){
ObjRender_SetPosition(extrashot, GetPlayerX-10, GetPlayerY-30, 3);
ObjRender_SetPosition(extrashot2, GetPlayerX+10, GetPlayerY-30, 3);
}
else{
ObjRender_SetPosition(extrashot, GetPlayerX-30, GetPlayerY-30, 3);
ObjRender_SetPosition(extrashot2, GetPlayerX+30, GetPlayerY-30, 3);
}
I know it's because of the SetPosition thing but I'm not sure how to make them NOT teleport. I've tried ObjMove_SetDestAtFrame and other things like that but it doesn't seem to do anything. Is there something else I can try?