|
Siegfreide
|
 |
« on: October 06, 2013, 07:12:21 PM » |
|
Basically, when the player fires bullets that make contact with the enemy and causes damage, I would like for the damage amount done to the enemy to be displayed on-screen at the bullet's collision point with the enemy. I would also like for this number to be color coded, based on where the damage was processed in the enemy(in the game I'm making, enemies have both "shields" and "hull", with the hull pretty much just being hitpoints). I'll give a brief example in the form of a descriptive scene, to try and illustrate what I would like to achieve below; ""I find the enemy, and press the left mouse button to 10 bullets at it. All 10 bullets make contact, and do damage to the enemy. The first 7 bullets damage only the shield, and send raising,quivering(waving back and forth) BLUE numbers, indicating how much damage I did and that the damage was dealt to the shield. The first 7 bullets did enough damage to drain the shield, and the last 3 bullets damage the armor directly, sending GREEN raising, quivering damage numbers at the bullets collision point. Each instance of number stays on-screen for about 3 seconds, or 90 steps, and after that the alpha fades to 0, and the instance is destroyed."" So far, this is what my coding looks like; obj_enemy CREATE;----------------------------
shield = 10; hull = 20;
//shield is active shieldActive = 1;
bullet_count = 500;
timer_bullet = 0;
destroyed=0;
obj_enemy STEP;-----------------------------
////Death upon losing all hull
if (hull <= 0 && destroyed=0) { destroyed = 1; instance_create(x, y, obj_explosion); image_index=12; }
////Fire Bullets at the player
if destroyed=0 { // check if there are no walls in a straight line towards the object "obj_player" if !collision_line(x,y,obj_player_mech.x,obj_player_mech.y,obj_wall,false,true) { if bullet_count > 0 && timer_bullet=0 { instance_create(x,y,obj_bullet_enemy); bullet_count-=1; timer_bullet=10; } } if timer_bullet>0 { timer_bullet-=1; } }
image_speed=0;
////Determine if Shield is active or faulty
if shield > 0 { shieldActive = 1; } else { shieldActive = 0; } obj_bullet CREATE;-----------------------
move_towards_point(mouse_x,mouse_y,30); image_angle = direction;
firepower = 1;
obj_bullet STEP-------------------------
hit = instance_place(x,y,obj_enemy); damageShield = (hit.shield-firepower); damageHull = (hit.hull-firepower); damageText = 1; damageText.amount = damageShield || damageHull;
/* if(obj_enemy.shield = 1) { damageText.shieldActive = true; } else { damageText.shieldActive = false; } */
if collision_point(x,y,obj_wall,false, true) { instance_destroy(); }
if (hit != noone && obj_enemy.shieldActive = 1) { hit.shield -= firepower; instance_create(obj_bullet.x,obj_bullet.y,obj_damage); damageText=1; instance_destroy(); } else if (hit != noone && obj_enemy.shieldActive = 0) { hit.hull -= firepower; instance_create(obj_bullet.x,obj_bullet.y,obj_damage); damageText=0; instance_destroy(); } obj_damage CREATE;------------------------
direction = 90; //float up speed = 5;
timer_damageShow = 90;
obj_damage STEP;--------------------------
////Damage Number Movement and Timing
if timer_damageShow>0 { timer_damageShow-=1; } else { instance_destroy(); }
/* move_towards_point(x+20,y-10,5)
then, move_towards_point(x-40,y-10,5)
then, move_towards_point(x+40,y-10,5)
then, text fade alpha to 0
if alpha = 0, instance_destroy() */
obj_damage DRAW;--------------------------
////Draw Player-Inflicted Damage Amount
if obj_enemy.shieldActive=1 { draw_text(x,y,string(obj_enemy.damageShield)); draw_text_color(x,y,string(obj_enemy.damageShield),c_white,c_white,c_white,c_white,1); } else if obj_enemy.shieldActive=0 { draw_text(x,y,string(obj_enemy.damageHull)); draw_text_color(x,y,string(obj_enemy.damageHull),c_white,c_white,c_white,c_white,1); } As it currently stands, this code does not work. The instant I try to fire bullets, I am met with this message; ###################################################### FATAL ERROR in action number 1 of Draw Event for object obj_damage: Push :: Execution Error - Variable Get 5.damageShield(100018, -1) at gml_Object_obj_damage_Draw_0 (line 5) - draw_text(x,y,string(obj_enemy.damageShield)); ######################################################## So, where should I begin fixing this?
|
|
|
|
« Last Edit: October 07, 2013, 11:41:39 AM by Siegfreide »
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #1 on: October 06, 2013, 07:30:42 PM » |
|
all you have to do is this. in the bullet's destruct event, have it turn into a damage indicator object (if it hit an enemy). have it spawn at the same location as the bullet was when the bullet was destroyed
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #2 on: October 06, 2013, 07:33:56 PM » |
|
all you have to do is this. in the bullet's destruct event, have it turn into a damage indicator object (if it hit an enemy). have it spawn at the same location as the bullet was when the bullet was destroyed
I was originally going to have the bullet destroy itself, and have obj_damage created in it place, but just changing the instance sounds easier. But still, how should I make it write the appropriate text? And make it slowly fade to alpha=0?
|
|
|
|
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #3 on: October 06, 2013, 07:39:27 PM » |
|
if you use alarms, you can set its alpha value to its alarm over its max alarm. e.g. if you set the alarm[0] to 100 when it is created, just set the alpha value to alarm[0]/100
as for writing the text, when you create it, assign it a string with the damage number. for example:
damage_id = instance_create(blah blah) damage_id.str = string(damage);
then use draw_text(x, y, str) in the draw event of the damage indicator object
this is pretty basic stuff you are asking you know, maybe you should read the manual again. it should answer most of the questions you are having
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #4 on: October 06, 2013, 07:53:05 PM » |
|
Dont get me wrong, I know how to draw text and all that good stuff. I'm just having a problem with this particular instance for some reason or another. So, given the above information, in my obj_damage CREATE event, it should look something like this? direction = 90; //float up speed = 5;
timer_damageShow = 100; timer_alpha = 100;
in the STEP of obj_damage; ////Damage Number Movement and Timing
if timer_damageShow>0 { timer_damageShow-=1; } else { instance_destroy(); }
if timer_alpha>0 { timer_alpha-=1 }
/* move_towards_point(x+20,y-10,5)
then, move_towards_point(x-40,y-10,5)
then, move_towards_point(x+40,y-10,5)
then, text fade alpha to 0
if alpha = 0, instance_destroy() */
and in the DRAW event of obj_damage; ////Draw Player-Inflicted Damage Amount
if obj_enemy.shieldActive=1 { draw_text(x,y,string(obj_enemy.damageShield)); draw_text_color(x,y,string(obj_enemy.damageShield),c_white,c_white,c_white,c_white,timer_alpha/100); } else if obj_enemy.shieldActive=0 { draw_text(x,y,string(obj_enemy.damageHull)); draw_text_color(x,y,string(obj_enemy.damageHull),c_white,c_white,c_white,c_white,timer_alpha/100); }
Even still, I have no idea where these should be located, or where to tie them in to; damage_id = instance_create(blah blah) damage_id.str = string(damage);
|
|
|
|
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #5 on: October 06, 2013, 07:56:52 PM » |
|
something like that should work, but you don't need to put brackets around single-lines, and you don't need to have a separate counter for the alpha and for the timer until it destroys itself, since both go from 100 to 1 they are in effect the same number, you can use one value for both. i think what you wrote should work but it could be done in like 5 lines of code instead of the 25+ you are using for instance, one reason i suggested alarms is because they are automatically decremented by 1 each step, and you can add a destroy action when the alarm hits 0, which saves a lot of coding time i mean, look at this: if timer_damageShow>0 { timer_damageShow-=1; } else { instance_destroy(); }
if timer_alpha>0 { timer_alpha-=1 } vs (removing brackets) if timer_damageShow>0 timer_damageShow-=1; else instance_destroy();
if (timer_alpha>0) timer_alpha-=1
vs (using alarms and a destroy action in the alarm event)
|
|
|
|
« Last Edit: October 06, 2013, 08:02:17 PM by Paul Eres »
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #6 on: October 06, 2013, 08:04:34 PM » |
|
I agree, the D&D function is definitely very useful. However, it was suggested to me that hard-coding all of the GML into the CREATE, STEP and DRAW event is the best way to learn how the code interacts with the game, as well as learning different workarounds and such. Thats why I'm having to do everything the hard way lol.
EDIT; I use the brackets to make it easier for me to read the code. I have yet to obtain a coder's eyes, I'm still a beginner >.>
|
|
|
|
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #7 on: October 06, 2013, 09:27:14 PM » |
|
i don't understand how that could be easier to read, but different people have different styles. using braces for single statements is pretty common, and has the advantage of avoiding some common mistakes. i didn't mean to say that you're wrong about it. it's just that it never made sense to me to use four lines for what can be done in two (or sometimes one, i occasionally do stuff like "if (powerup[3] >= 1) creature_slow();" on a single line)
the main redundancy though is that you have two variables which count down, identically, from 100 to 0. considering that both of those variables are always exactly the same, i don't think it makes sense to use them both. even if you don't use alarms, one variable is sufficient
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #8 on: October 06, 2013, 09:37:10 PM » |
|
i don't understand how that could be easier to read, but different people have different styles. using braces for single statements is pretty common, and has the advantage of avoiding some common mistakes. i didn't mean to say that you're wrong about it. it's just that it never made sense to me to use four lines for what can be done in two (or sometimes one, i occasionally do stuff like "if (powerup[3] >= 1) creature_slow();" on a single line) Mainly, its just the uniformity of it all that makes it more comprehensible. And i think you're right, fewer lines should also me fewer mistakes, which Im definitely all about. I guess I'm trying to say that while I would definitely be interested in learning to code more efficiently, I feel I need to get he basics down first. the main redundancy though is that you have two variables which count down, identically, from 100 to 0. considering that both of those variables are always exactly the same, i don't think it makes sense to use them both. even if you don't use alarms, one variable is sufficient
I totally agree with you, its absolutely redundant. Its been a long day, and I've come far, but i suppose the effect of lack of sleep is beginning to rear its gnarly head. Creating this game is just too damn exciting though, I wouldn't be able to sleep if I tried.
|
|
|
|
« Last Edit: October 06, 2013, 10:25:05 PM by Siegfreide »
|
Logged
|
|
|
|
|
|
|
Leon Fook
|
 |
« Reply #10 on: October 07, 2013, 05:22:58 AM » |
|
obj_enemy CREATE;----------------------------
shield = 10; hull = 20;
//shield is active shieldActive = 1;
bullet_count = 500;
timer_bullet = 0;
destroyed=0;
obj_enemy STEP;-----------------------------
////Death upon losing all hull
if (hull <= 0 && destroyed=0) { destroyed = 1; instance_create(x, y, obj_explosion); image_index=12; }
////Fire Bullets at the player
if destroyed=0 { // check if there are no walls in a straight line towards the object "obj_player" if !collision_line(x,y,obj_player_mech.x,obj_player_mech.y,obj_wall,false,true) { if bullet_count > 0 && timer_bullet=0 { instance_create(x,y,obj_bullet_enemy); bullet_count-=1; timer_bullet=10; } } if timer_bullet>0 { timer_bullet-=1; } }
image_speed=0;
////Determine if Shield is active or faulty
if shield > 0 { shieldActive = 1; } else { shieldActive = 0; } As it currently stands, this code does not work. The instant I try to fire bullets, I am met with this message; ###################################################### FATAL ERROR in action number 1 of Draw Event for object obj_damage: Push :: Execution Error - Variable Get 5.damageShield(100018, -1) at gml_Object_obj_damage_Draw_0 (line 5) - draw_text(x,y,string(obj_enemy.damageShield)); ######################################################## So, where should I begin fixing this? After i look through your code, i think the error is trying to tell you that they can't find the variable "damageShield" in obj_enemy. I would suggest that you don't address the variable "damageShield" in the object obj_enemy, instead, when you about to instance_destroy the bullet, pass the variable "damageShield" down to obj_damage. So it's something like: if (hit != noone && obj_enemy.shieldActive = 1) { hit.shield -= firepower; with instance_create(obj_bullet.x,obj_bullet.y,obj_damage) damagaShield = other.damageShield; damageText=1; instance_destroy(); }
then you can do something like: if obj_enemy.shieldActive=1 { draw_text(x,y,string(damageShield)); draw_text_color(x,y,string(damageShield),c_white,c_white,c_white,c_white,1); }
Also, don't depend on addressing variable on other object, such as your obj_enemy.shieldActive code above, instead, just pass down all the variable to that object that you wanna tell the object to use. Might save you some time hunting down the error like "no such instance exists"(like when your obj_enemy is destroyed before obj_damage), but it does have some weakness this way though, like memory consumption(or is it cpu)
|
|
|
|
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #11 on: October 07, 2013, 05:38:23 AM » |
|
i didn't see that he edited the first post. but yes, you are correct
the reason that error happens is because you are trying to access a value of a *destroyed object*. the object is gone, destroyed. it doesn't exist anymore. so you can't access its values anymore. that's why i said to give it a value to display when it's created
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #12 on: October 07, 2013, 11:09:16 AM » |
|
the reason that error happens is because you are trying to access a value of a *destroyed object*. the object is gone, destroyed. it doesn't exist anymore. so you can't access its values anymore.
But, I dont understand how that could be. When the enemy is "destroyed" the instance isnt actually destroyed. it only explodes and crumbles into a pile of scrap, but it remains on-screen and is interactive. However, I am going to take Leon Fook's advice and pass on the variable. I'll report whether that solved my issue or not.
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #13 on: October 07, 2013, 11:40:29 AM » |
|
Ok, this is what my new code looks like; obj_damage DRAW; if obj_enemy.shieldActive=true { draw_text(x,y,string(damageShield)); draw_text_color(x,y,string(damageShield),c_blue,c_blue,c_blue,c_blue,timer_damageShow/100); } else { draw_text(x,y,string(damageHull)); draw_text_color(x,y,string(damageHull),c_green,c_green,c_green,c_green,timer_damageShow/100); }
obj_bullet STEP; damageShield = firepower; damageHull = firepower; hit = instance_place(x,y,obj_enemy);
if collision_point(x,y,obj_wall,false, true) { instance_destroy(); }
if (hit != noone) { if obj_enemy.shieldActive=true { hit.shield-=firepower; with instance_create(x,y,obj_damage) damageShield = other.damageShield; } else if obj_enemy.shieldActive=false && hit.hull > 0 { hit.hull-=firepower; with instance_create(x,y,obj_damage) damageHull = other.damagehull; } instance_destroy(); }
obj_enemy STEP; if shield > 0 { shieldActive = true; } else { shieldActive = false; }
Now, everything works perfectly... as long as the enemy still has some shield left. However, when the transition from damageShield to damageHull is supposed to occur, I'm less than pleasantly greeted with this message; FATAL ERROR in action number 1 of Draw Event for object obj_damage: Push :: Execution Error - Variable Get -1.damageHull(100022, -1) at gml_Object_obj_damage_Draw_0 (line 27) - draw_text(x,y,string(damageHull)); I've checked and double-checked my code, and I can't figure out what the problem is now. damageHull is written exactly like damageShield, in terms of form, so I can't see where the issue is arising from.
|
|
|
|
|
Logged
|
|
|
|
|
Leon Fook
|
 |
« Reply #14 on: October 07, 2013, 06:27:58 PM » |
|
FATAL ERROR in action number 1 of Draw Event for object obj_damage:
Push :: Execution Error - Variable Get -1.damageHull(100022, -1) at gml_Object_obj_damage_Draw_0 (line 27) - draw_text(x,y,string(damageHull));
I've checked and double-checked my code, and I can't figure out what the problem is now. damageHull is written exactly like damageShield, in terms of form, so I can't see where the issue is arising from.
Fatal error? Not fatal at all. Did you copy all the code directly or you retype it? I mean in term of your post. Because: obj_bullet STEP; (code) ... else if obj_enemy.shieldActive=false && hit.hull > 0 { hit.hull-=firepower; with instance_create(x,y,obj_damage) damageHull = other.damagehull; } instance_destroy(); } (/code)
It just a minor spelling error. But, I dont understand how that could be. When the enemy is "destroyed" the instance isnt actually destroyed. it only explodes and crumbles into a pile of scrap, but it remains on-screen and is interactive.
Did the obj_enemy still exist when it hp is all drain out? I mean, did you use the instance_destroy() when it die or just simply hide it? It's reasonable to hide it so you can excess it data, like resurrect it later, other than that, it's not encouraged to do so. It's okay if you like fighting your enemy 1 on 1, but if it's some epic battle, it will easily rake up the instance and cause slowdown. What Paul said make sense, if you think it that way.
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #15 on: October 07, 2013, 06:36:31 PM » |
|
Did the obj_enemy still exist when it hp is all drain out? I mean, did you use the instance_destroy() when it die or just simply hide it? It's reasonable to hide it so you can excess it data, like resurrect it later, other than that, it's not encouraged to do so. It's okay if you like fighting your enemy 1 on 1, but if it's some epic battle, it will easily rake up the instance and cause slowdown. What Paul said make sense, if you think it that way.
When the enemy dies, I leave them on-screen to be looted by the player (although I admit I haven't figured that one out yet). After the enemy is looted, I THEN want the obj_enemy instance to instance_destroy();. There isnt any resurrection going on, all the enemies that exist, already exist, and destroying them just subtracts the permanent global enemy count.
|
|
|
|
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #16 on: October 07, 2013, 06:37:35 PM » |
|
side note, but you realize that string() is very slow right? you don't want to perform string() every step. each step it's going through the same process of converting a number into a string, which makes no sense. it'll slow the game, especially if you have a ton of damage indicators on screen at once. use string() on the value *once*, when it's created, and then use that created string from there after
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #17 on: October 07, 2013, 06:47:01 PM » |
|
side note, but you realize that string() is very slow right? you don't want to perform string() every step. each step it's going through the same process of converting a number into a string, which makes no sense. it'll slow the game, especially if you have a ton of damage indicators on screen at once. use string() on the value *once*, when it's created, and then use that created string from there after
No, I have no clue as to the theoretical speeds of coding, I'm practically brand new to GML and coding in general :/ So, instead of; with instance_create(x,y,obj_damage) damage=other.damage; Use this? with instance_create(x,y,obj_damage) string(damage)=other.string(damage);
|
|
|
|
|
Logged
|
|
|
|
|
ஒழுக்கின்மை
|
 |
« Reply #18 on: October 07, 2013, 07:10:24 PM » |
|
no, do str_damage = string(other.damage)
and then use str_damage directly in the draw_text, without the string() anymore
|
|
|
|
|
Logged
|
|
|
|
|
Siegfreide
|
 |
« Reply #19 on: October 07, 2013, 07:14:17 PM » |
|
no, do str_damage = string(other.damage)
Sorry, but I'm still a bit confused. You mean this? //setting the variable str_damage=firepower;
with instance_create(x,y,obj_damage) str_damage)=string(other.damage);
And inside obj_damage DRAW draw_text_color(x,y,damage,c_blue,c_blue,c_blue,c_blue,timer_damageShow/50);
////Or this////
draw_text_color(x,y,str_damage,c_blue,c_blue,c_blue,c_blue,timer_damageShow/50);
|
|
|
|
|
Logged
|
|
|
|
|