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: