Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411468 Posts in 69368 Topics- by 58422 Members - Latest Member: daffodil_dev

April 23, 2024, 01:21:39 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperPlaytestingCharge Shot / Archery experiment
Pages: [1]
Print
Author Topic: Charge Shot / Archery experiment  (Read 1846 times)
8Points
Level 1
*



View Profile WWW
« on: February 11, 2014, 01:00:53 PM »

Hey guys, I threw together a little concept for a shooting system in a couple hours and I want to see if it feels good. It's supposed to emulate drawing and firing an arrow of some sort.

Anyway, here's the dropbox link to the executable: https://www.dropbox.com/s/w981sjgintye9tt/Shooty_Face.exe

EDIT: Now contains explosions.
EDIT 2/14/14: Sweet spot and variable damage applied as suggested by crumpet - releasing your shot during the sweet spot will do double damage!
EDIT 2/25/14: New level! New charge sprite! Better feel!
EDIT 2/25/14 II: Added an AoE attack - push enemies away by click the right button!

You are the green blob, WASD to move, aim with mouse cursor, hold left mouse button to charge, release to shoot. Hit the targets!

Aaaand here are some screenshots - though they're not much to look at:





Thanks!
« Last Edit: February 25, 2014, 03:48:48 PM by 8Points » Logged
jusk
Level 0
**



View Profile
« Reply #1 on: February 11, 2014, 04:08:19 PM »

As a single mechanic it's not bad at all. The charge aspect works well. Certainly seems a decent starting point for archery type shooter.  Gentleman
Logged

8Points
Level 1
*



View Profile WWW
« Reply #2 on: February 11, 2014, 04:34:31 PM »

Thank you, sir! I plan on plopping this into a dungeon diver type game, just gotta make sure it's fun first!
Logged
noethis
Level 0
**


View Profile
« Reply #3 on: February 12, 2014, 07:43:23 AM »

Just tried it out--a cool mechanic and something very similar to what I'm doing in a prototype I've been working on. One thing that might help is to convey the charge amount more clearly--just having the little thing light up in the middle didn't seem to be enough to communicate how charged I was.
Logged

8Points
Level 1
*



View Profile WWW
« Reply #4 on: February 13, 2014, 03:56:05 PM »

I didn't spend very long at all on the arts for this, and I definitely agree with you that it needs a better way to indicate charge levels, but I assume all that will taken care of when the real art is implemented. There will probably be a little animation of a dude drawing back his bow, which will hopefully be a better indicator. Got a link to your prototype? It's always interesting to see how other people handle similar themes.
Logged
crumpet
Level 0
**


I did a art, once


View Profile WWW
« Reply #5 on: February 13, 2014, 06:02:02 PM »

The best thing about this kind of mechanic is, if well implemented, it can make the player feel more skilled, and possibly even just feel plain ol' badass.
The big thing is it needs to be very well implemented if you want this, otherwise it just becomes another thing on the player's checklist, more a chore than a skill.

It's still early in design, so if that's what you want, then you're in an excellent position to go for it! Here's what I'd recommend doing:

1) Have a set amount of charging time (eg: between 1.4 and 1.5s) where you can get a perfect shot. Make the player flash, or some kind of visual cue to show that this is a good time. Firing at this time would result in a much more powerful/long ranged/high speed shot. Charge any less, and the shot is lacking in range/power. Charge any longer, and the shot loses some power/accuracy/range. The crucial bit is you keep the timing window small, constant, and rewarding. Bastion is a great example of how to do this

2) You need a penalty for charging. Lots of games make you move more slowly when you're charging a shot. Try this out, see if it works for you. You need to impose some penalty for charging too long, or your players will just hold charge forever between battles. That can work, Megaman games do it fine, but I would say some kind of movement penalty for charging would help.

3) Visual/audio cues. Make it very clear how much the player wants to charge it. Don't spell it out to them either, let them learn the mechanic themselves. A mechanic that teaches itself is a very satisfying one to learn.

That's all I can really think of now, I might be able to give you more when you've made more. My advice isn't word of God, either. It's advice. A lot of it stands on what you plan on doing in this game Smiley
Logged

I used to think I was a failure. Then I discovered you can just buy trophies. Now I win at everything.
8Points
Level 1
*



View Profile WWW
« Reply #6 on: February 13, 2014, 06:49:03 PM »

Thanks, man! That sweet-spot for charging is a fantastic idea!! I'll definitely try implementing that tonight.

In terms of penalty for charging, I actually reduce the player's movement speed depending on how long they've been charging up. When fully charged their speed is at half their normal speed, with like 3 different speeds in between matched up with the charge level. Maybe this isn't harsh enough - it's only 1 pixel per frame slower than the enemy's speed. It's a slow, gradual slide into this slower speed too, with a proportionately significant drop-off at full charge. Maybe switch the drop off to the beginning of the process...? I guess I'll have to mess around.

I'm hesitant to put a lot of effort into the audio/visual aspect of this though. Since it's only one mechanic in what will be more significant game, I don't want to do a bunch of work on the aesthetics only to redo it all to fit the grand theme (which I don't have nailed down yet). I agree, though, that is imperative that they communicate the different states properly, while not spelling it out entirely. Ah, balance...

Again, thanks for taking the time to play! And more so for the feedback! and yet MORE so for sweet-spot concept!! I'll try to have that implemented by the end of the night (read: by sunrise)
Logged
crumpet
Level 0
**


I did a art, once


View Profile WWW
« Reply #7 on: February 13, 2014, 08:06:09 PM »

For the audio-visual, just look at what Bastion does. It just makes your character whiter at the sweet spot, which you can do in code, without having to change your character graphics at all Smiley

Check this video for what I mean:


Logged

I used to think I was a failure. Then I discovered you can just buy trophies. Now I win at everything.
8Points
Level 1
*



View Profile WWW
« Reply #8 on: February 14, 2014, 02:52:03 PM »

Ah, I'm not sure I can change the color of a sprite in-game without the upgraded version of GameMaker. I did make a simple sprite that should clearly indicate when the sweet spot is occurring. I'll update my original post with a link to the new version.

Oh, there is a weird bug I can't pin down where if you release your shot during the sweet spot, it will sometimes spawn more than 1 bullet. I'll try to solve it, but I may leave it in there anyway as a strange bonus for landing that perfect shot if I can't figure it out in time.
« Last Edit: February 14, 2014, 03:03:56 PM by 8Points » Logged
oodavid
Level 8
***


Discombobulate!


View Profile WWW
« Reply #9 on: February 15, 2014, 03:57:51 AM »

Tis good, if your game will have a heavy focus on archery then you should try to plan out different scenarios and mechanics, such as:

* Ricochet when hitting walls at acute angles
* Setting on fire when passing through torches (or to be more general, inheriting attributes)
* Splintering into two when hitting enemy blades
* Sticking into walls to create block enemy passage
* Shooting over half-walls / through windows
* Pinning Enemies

etc. etc.

Demo was good, found it too rapid to destroy more than a few targets, ran through Wine on Linux so it may not be your fault!

Logged


Button up! - Out on Android and iOS

latest release: 13th March 2015
crumpet
Level 0
**


I did a art, once


View Profile WWW
« Reply #10 on: February 16, 2014, 10:56:49 AM »

Quote
Oh, there is a weird bug I can't pin down where if you release your shot during the sweet spot, it will sometimes spawn more than 1 bullet. I'll try to solve it, but I may leave it in there anyway as a strange bonus for landing that perfect shot if I can't figure it out in time.

Trust me, you DON'T want that xD
Try and fix it... You said it's in Gamemaker, I'm a Gamemaker person myself Tongue
Explain to me, how does your code work? I can see if I can figure out what you may be doing wrong Smiley
Logged

I used to think I was a failure. Then I discovered you can just buy trophies. Now I win at everything.
8Points
Level 1
*



View Profile WWW
« Reply #11 on: February 16, 2014, 12:23:57 PM »

@oodavid That's quite the list! All of those sound like really cool mechanics, but my game won't be entirely focused on archery - actually I probably should have explained what this system was getting put in to...

It's a very small dungeon diver game in the vein of Gauntlet, I'm trying to get it done by the beginning of March for my self-imposed monthly game challenge. You choose from one of three characters and take them through probably no more than 3 levels. The archer is just one of the characters, amongst a melee guy who can leap to close distances and a mage-y dude who's mechanics I haven't fully conceived, but will probably involve explosions and chain reactions. I'm keeping the scope as small as I can so I'll actually be able to finish it come March, so while the ideas you provided are awesome, they probably won't make it into the game :/ ricochet bullets might make it in if I can figure it out easily...

@crumpet Oh man, thanks! I'm not sure I want to fill up this thread with my code - it's not an incredible amount but still... Anyway, here's what I assume is relevant:

obj_green is the archer player character
its create event:
Code:

sp = 9; //speed
c_sp = 5; //charging speed, how fast you move when charging a shot
n_sp = sp; //normal speed, how fast you move when not charging a shot

shot_ready = 0;
shot_true = 0; //Ticks on for the sweet spot, massive damage?

charging = 0;
charge_ready = 1;

key_shoot = 0;  sd = 0;

its begin step event:
Code:
charge_level = 0; //create variable that holds obj_shot_charge's charge_level to pass to obj_bullet
c_sp = 5;

if mouse_check_button_pressed(mb_left){key_shoot = 1;}
if mouse_check_button_released(mb_left){key_shoot = 0;}

if key_shoot == 1
{
    if  charging == 0 && charge_ready == 1
    {
        sp = c_sp;
        charging = 1;
        charge_ready = 0;
        instance_create(x,y,obj_shot_charge); //charger plays animation, creates obj_shot_ready that sets "shot_ready" to 1 when finished, set various charge levels for obj_bullet to reference
    }
    else if instance_exists(obj_shot_charge)
    {
        charge_level = obj_shot_charge.charge_level;
        switch (charge_level)
        {
            case 0: c_sp = 9 break;
            case 1: c_sp = 8 break;
            case 2: c_sp = 7 break;
            case 3: c_sp = 4 break;
        }  
    }
}
else
{
    sp = n_sp;
    if shot_true = 1 //I THINK THIS IS WHERE THE PROBLEM IS!!
    {
        charge_level = 4;
        bullet = instance_create(x,y,obj_bullet);
        with (bullet){charge_level = 4;}
        shot_true = 0;
        charging = 0;
        alarm[0] = 15; //charge_ready alarm
    }
    else if shot_ready = 1
    {
        charge_level = 3;
        bullet = instance_create(x,y,obj_bullet);
        with (bullet){charge_level = 3;}
        shot_ready = 0;
        charging = 0;
        alarm[0] = 15; //charge_ready alarm
    }
    else if instance_exists(obj_shot_charge)
            {
                if obj_shot_charge.charge_level > 0
                {
                    charge_level = obj_shot_charge.charge_level;
                    bullet = instance_create(x,y,obj_bullet);
                    shot_ready = 0;
                    charging = 0;
                    alarm[0] = 15; //charge_ready alarm
                }
                else
                charging = 0;
                alarm[0] = 15; //charge_ready alarm
                with(obj_shot_charge){instance_destroy();}
            }
}

its alarm[0] event:
Code:
charge_ready = 1;

it moves with WASD key press events, but I don't think those are relevant to this problem.

obj_shot_charge is an object that spawns when charging a shot and tracks how long the charge is held. It plays a 20 frame animation and then turns into obj_shot_true for a moment that then turns into obj_shot_ready.

obj_shot_charge create event:
Code:
charge_level = 0; //Tracks how long the shot is charged, bullet distance/strength is based on this

//alarms trigger the charge level changes, and are based on the animation length
alarm[0] = 7; //Weak
alarm[1] = 14; //Medium
alarm[2] = 19; //Full

those alarm events only change the value of charge_level.

it has an end step event that sets its x,y coordinates to the player's.

its animation end event:
Code:
instance_change(obj_shot_true,true);

obj_shot_true create event:
Code:
obj_green.shot_true = 1;

alarm[0] = 5;

its alarm[0] event:
Code:
obj_green.shot_true = 0;

instance_change(obj_shot_ready,true);

its end step event:
Code:
x = obj_green.x;
y = obj_green.y;

if instance_exists(obj_bullet) instance_destroy();

obj_shot_ready create event:
Code:
obj_green.shot_ready = 1;

its end step event:
Code:
x = obj_green.x;
y = obj_green.y;

if instance_exists(obj_bullet) instance_destroy();

annnnddd obj_bullet is what gets shot.
its create event:
Code:
var charge_level, range, dmg, sp; //to be determined in the end step

chosen = 0; //checks when everything is set in end step so it doesn't do it again

dir = point_direction(obj_green.x,obj_green.y,mouse_x,mouse_y)

its alarm0 event:
Code:
instance_destroy();
instance_create(x,y,obj_boom);

its end step event:
Code:
if chosen == 0 //do this only once
{
    charge_level = obj_green.charge_level; //controls speed and damage variables
    switch (charge_level)
    {
        case 0: sp = 4; dmg = 0; range = 10; break;
        case 1: sp = 12; dmg = 5; range = 20; break;
        case 2: sp = 16; dmg = 10; range = 20; break;
        case 3: sp = 20; dmg = 20; range = 40; break;
        case 4: sp = 20; dmg = 40; range = 40; break;
    }
    
    motion_set(dir,sp);
    
    alarm[0] = range; //Controls how far bullets fly
    
    chosen = 1;
}

it also has collision events with obj_wall and obj_target, but they just destroy the instance and make the explosion animation object.

Sorry to flood this thread with code! I'll take it all down if need be, I have a dropbox link to the full project I can post in its place.

The weird part is that when I coded the sweet spot stuff in there I just copy and pasted the shot_ready function and hanged the variable names, and with obj_shot_true I just duplicated obj_shot_ready and had it send different values to the player. It all works, I'm just not sure why it isn't turning off the ability to shoot... Thanks for taking an interest, man!
Logged
crumpet
Level 0
**


I did a art, once


View Profile WWW
« Reply #12 on: February 16, 2014, 04:04:05 PM »

Right, let's get doing this!
I'll try and explain my thought process, since I may get my theory wrong, and in which case, you can try and see where I went wrong in... trying to figure out when your code went wrong.
...man, this might get complicated  Cheesy

So the problem is that two arrows are being created sometimes. This is presumably coming from the step event of obj_green, because as far as I can tell, that's the only time you ever create objBullet.

What I would do myself, right off the bat, is right next to each bit of the code that creates a bullet, make it cause a little pop up.

For example, when you create the bullets of charge level 4, a bit of your code looks like this:
Code:
        charge_level = 4;
        bullet = instance_create(x,y,obj_bullet);
        with (bullet){charge_level = 4;}

I would just add a simple line, make it like this:

Code:
        charge_level = 4;
        bullet = instance_create(x,y,obj_bullet);
        with (bullet){charge_level = 4;}
        show_message("The bullet has charge level 4.");

Do that for the other two bits in the code where it creates bullets. Who knows, it may turn out that you're creating a bullet of charge level 4 and a bullet of charge level 3 in the same step. This would help you find out a bit more about where the error is.

Then again, given all the else ifs, that doesn't look like it'll be the problem...
Again, we look at the three different places that a bullet gets created. Based purely off your if statements ("if shot_true = 1", "else if shot_ready = 1" and "else if instance_exists(obj_shot_charge)"), ignoring every other bit of code, try and track down what might cause this problem.

If "key_shoot = 0" is true for two steps in a row, it'll go through all the if statements twice in a row. This is very likely (as most players won't immediately start charging an arrow the moment they've loosed one). This means that any of the following could cause double arrows:
  • shot_true == 1 and shot_ready == 1
  • shot_true == 1 and (instance_exists(obj_shot_charge) and obj_shot_charge.charge_level > 0)
  • shot_ready == 1 and (instance_exists(obj_shot_charge) and obj_shot_charge.charge_level > 0)
  • A single one of your ifs being true, and not made false by next step

With the method I mentioned before of putting a show_message in next to each of your instance_create(x,y,obj_bullet) lines, you should hopefully be able to track down which of the above possibilities is causing the problem. Then just... make them false... Err...
I'm having a lot of trouble explaining this, so I'll just write up some psudo code to make my thoughts clearer.

So here's a little series of things which loosely mimics what you have:

Code:
if bullet_ready = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 3;}
    bullet_ready = 0;
}

else if bullet_true = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 2;}
    bullet_true = 0;
}

else if bullet_done = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 0;}
    bullet_done = 0;
}

The first thing I'm saying you should do is add a bunch of show_messages, make it more like this:

Code:
if bullet_ready = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 3;}
    bullet_ready = 0;
    show_message("Bullet created, charge 3");
}

else if bullet_true = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 2;}
    bullet_true = 0;
    show_message("Bullet created, charge 2");
}

else if bullet_done = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 0;}
    bullet_done = 0;
    show_message("Bullet created, charge 0");
}

Now run your game. Run it until two bullets are being created. When it happens, let's say you get two messages.
"Bullet created, charge 3"
"Bullet created, charge 0"

This means that somehow, both bullet_ready = 1 and bullet_done = 1 are returning true.
One easy fix that may or may not work would just be to add "bullet_done = 0" inside the first if, like so:

Code:
if bullet_ready = 1
{
    with (instance_create(x,y,obj_bullet)) {charge = 3;}
    bullet_ready = 0;
    bullet_done = 0;
    show_message("Bullet created, charge 3");
}

If that works, yipee! It might also not work. If that's the case, move on to the next thing.

If the solution I just gave didn't work, or if your messages are both the same, like:
"Bullet created, charge 2"
"Bullet created, charge 2"
Then it gets nastier. It means that somewhere else in your code, something is setting bullet_true to be 1 again, when it shouldn't. That's harder to find, you'll have to trawl through it all.

I can't actually see the problem myself in the code, it's really hard to understand what happens just from the game. So I'd recommend trying to fix the problem yourself (that's always better than getting someone else to do it, because then you can learn more about problem fixing Tongue). If you can't find it, you seem happy to share the source, so you could do that, and I could try and find the problem. But honestly, that should always be a last resort. I'm sure you can find and fix the problem yourself Smiley
Logged

I used to think I was a failure. Then I discovered you can just buy trophies. Now I win at everything.
8Points
Level 1
*



View Profile WWW
« Reply #13 on: February 16, 2014, 06:31:47 PM »

Oh man, I gotta remember that show_message method for next time.

I went in and added those messages like you suggested, so when I hit the problem I got a message for the 'true' shot followed immediately by a 'ready' shot message. Ah, so the problem was that it after going through the shot_true function it would sometimes skip the else? Or is was it that shot_ready was set to true for the next step... So I put 'shot_ready = 0' at the very bottom of the function, hoping that would stop it from going onto the next function. It didn't change anything as far as I could tell.

So I put 'exit;' just beneath that, which I had actually tried before. I'm not sure why it didn't do the trick last time, but this time it worked. I've tested it for like 10 minutes and it seems to working just fine! I guess the combination of turning off shot_ready AND exiting the event was what it needed, though I wish I understood why. I thought it might have something to do with obj_shot_true turning into obj_shot_ready in an alarm event, which would mean that obj_green creates a bullet in it's begin step and set's everything square only to be re-done just before the next frame. I'm not sure that's how it works though... I wish I had a better understanding of GM!!

Anyway, I know I say this a lot but I really REALLY appreciate you helping me out, man. It works the way I want it to now, so I can move on to the other characters. Fingers crossed it all works properly! Oh, and thanks for the confidence!! XD
Logged
crumpet
Level 0
**


I did a art, once


View Profile WWW
« Reply #14 on: February 17, 2014, 07:20:21 AM »

No problem! Happy to see you're so enthusiastic about a project!

Good luck with whatever may come further down the line Smiley
Logged

I used to think I was a failure. Then I discovered you can just buy trophies. Now I win at everything.
jgrams
Level 3
***



View Profile
« Reply #15 on: February 18, 2014, 04:09:31 AM »

1) Have a set amount of charging time (eg: between 1.4 and 1.5s) where you can get a perfect shot. Make the player flash, or some kind of visual cue to show that this is a good time. Firing at this time would result in a much more powerful/long ranged/high speed shot. Charge any less, and the shot is lacking in range/power. Charge any longer, and the shot loses some power/accuracy/range. The crucial bit is you keep the timing window small, constant, and rewarding. Bastion is a great example of how to do this

This made me think of Spy Party's Action Test, which has a window which is small and at a random position. I imagine this is a bad idea in your situation, but I thought I'd throw it out there just for fun:

http://www.spyparty.com/2011/01/04/how-i-celebrated-the-igf-nomination/
http://www.spyparty.com/2011/02/12/action-test-seduce-target-and-new-maps-playtest-reports/

--Josh
Logged
8Points
Level 1
*



View Profile WWW
« Reply #16 on: February 25, 2014, 12:05:42 PM »

That looks pretty interesting, but I think this game will benefit from having a consistent sweet spot.

Anyway, I updated the dropbox link in my original post, I created a sprite that follows your cursor when charging a shot, hopefully it will give it a better indication as to how charged you are and when the sweet spot will occur. I also slimmed the code down, changed the way the sweet spot is handled. I basically just made obj_shot_charge handle it like the other charge levels with some special variables. I also changed up the cooldown so that different levels of charge result in inversely-proportional lengthed cooldowns. If you land a true shot, there is no cooldown - I want there to be a rhythm to the shooting. If I put music in, you better believe I'll have the timing line up with the beat.

I still want to add another move for this character, for the right mouse button. I'm thinking a force field type thing that just pushes back anyone who is within its range. I figure that would be pretty useful for when enemies are coming from either side of you, and will give you enough time to position yourself for a better shot. It'll probably have a long cooldown to discourage players relying too heavily on it. What do y'all think?

And I'm working on a melee character as well, he's not as well tuned but it's a start. If you're interested, check him out here: https://www.dropbox.com/s/94mexi3x2ybmfks/Punchy_Face.exe

You left click to punch, and can hold the right mouse button to charge up a leap, which will kill anyone in your way. It's kind of broken in that the leap is too powerful, and I intend on countering that by making it only do damage where it ends, hence the reticle that shoots out of you. Its supposed to line up with where you'll land but it's a little off. Let me know what you think!

EDIT: I implemented the secondary ability for shooty face. Now when you right-click a hitbox will appear and push away any enemy who touches it - should be useful for getting out of close encounters.
« Last Edit: February 25, 2014, 03:50:55 PM by 8Points » Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic