Jump to content

BabylonJS 2.5 Challange - jppresents progress & blog [combat text & more 27.02.2017]


jpdev
 Share

Recommended Posts

This is another update - I finished the caster class today.

It's a mage that can casts two fire spells and a teleport.

Fireball: It has casttime and takes some time to reach the target and deal damage.
Fireblast: It deals the damage instantly but has a cooldown
Teleport: Let's you choose a target to teleport to instantly

My wife play tested the mage with me. I recorded the last session, so here is the first gameplay video:

 

Link to comment
Share on other sites

Thank you both for the praise :)

23 minutes ago, Raggar said:

How does the 'monsters' find their ways to your characters? They seem to follow you around, but it doesn't look like ray mechanics. Are you, like, saying player X attacked you, player X is at position Y, go to position Y?

Players and monsters move the same way:
If the player clicks somewhere or the monster decides to "roam" somewhere a target position of two values is set: x,z (y is frozen the whole game takes place on a fixed y plane).
If the player or the monster is in attack mode (for monsters this is triggered when they receive damage or a player gets to close) they have another object as their target, which just means every time the movement is calculated the x and z value of this target object are used as the target.

Each object has a fixed speed per second. When moving a vector towards the target is calculated (direction), it is then normalized (length = 1) and then scaled by the speed per second of the object divided by the elapsed time.
This vector is added to the current position. So everything moves in a straight line to their target.

After applying the movement vector collision is checked (monsters collide with other monsters and "the world" while players only collide with the world).
If a world collision is detected there is another check if moving only by the "x" axis avoids the collision, if that is the case only the x component of the movement vector is applied. If removing the "x" component does not help removing the z component is tested next. This way if the target is blocked by the world the object kind of "slides along" the obstacle as long at the target isn't straight behind it. You can see this in the gif posted here:

And lastly if there is a collision with another object (only active for monsters) then a vector describing the direction towards the blocking object is scaled by the movement speed and subtracted from the movement vector and this new smaller movement vector is applied and collision checked. This way monster some what get around each other. But since there is no real path finding more than three or four monsters clump up and they do not really surround their target. But since I do not plan for such high monster density anyway I am fine with this for now.

This is the clumping that happens with too many enemies:

horde.gif

 

 

 

 

 

Link to comment
Share on other sites

1 hour ago, Raggar said:

I thought about doing something similar with monsters in a future project. But using rays might just be bit too intensive on the server.

Hi Raggar,

I think it might not be clear enough in my description above: My server doesn't know anything about the 3d world.
All movement and collision takes place on a 2d plane (the server even uses x and y as the coordinates for everything, only in the clients this gets translated into x,y,z with a fixed y).
The information about the world on the server consists of a grid of values. Each value covers the information for a 2 by 2 square in the 3d world. The value tells the server if it's blocked or not.
You can kind of see this in this screenshot of my map in a previous posting:

tiled.png

Geen means it's open ground.Grey / Tree means it's blocked. When checking for collision the coordinates are "projected" into the grid and the value is checked.
For line of sight checks a direction vector is created and points along it are checked for collision.

The server sends this map information to the clients on login - they not only use it for client side collision but also to "plant" trees and rocks in the level.

I am working on having more 3d terrains (gameplay still only on one plane) but to have it look nicer - this 3d representation is only client side and the parts are simply marked as blocking in the map data.

It looks like this:

terrain.png

The elevated rock areas are marked as blocking on the 2d map.

Link to comment
Share on other sites

  • 2 weeks later...

Hi guys,

This is a quick update.. I am totally running out of time and my todo list won't really shrink down and it's only seven more days.

I finalized the small area in which the game will be played, here is what it looks in blender:

island.png

Very simple and the whole usable area is completely flat - but that was the plan all along.

 

I changed the way the nameplates are displayed - I was using planes with billboard settings before, now I changed it an I am using Canvas2D:

nameplates.png

This way they are alway "flat" and the same size. Also "above" any scenery so no enemy can hide behind a tree and not be targetable. (You can click the nameplates to select the enemy just as you can click its mesh.)

The new feature (requested after the first healer play test) are the health bars attached to every nameplate - so you can see whom to heal. Or in case of beeing a damage dealer you can see which targets have already taken damage.

I also removed the meele attacks from the caster and the healer. They were pretty pointless - but now I have to replace them with another skill. (How you grow a todo list 101...)

Link to comment
Share on other sites

I can totally see how such a todo list would be laughable to you. [Edit: Did not take it to be meant in a mean way at all.]

.. I shutter when I try to imagine your todo list(s) for features / bugs / help requests and so much more for babylonJS.

I guess it's a good time to say: thank you and all contributors for all the work on babylonJS :)

Link to comment
Share on other sites

Three days until the challenge is over..

I am now sure, that I will have something for you guys to play - today at work on the lunch break I had four people (including myself) playing and everything worked!
Yes okay, there was a small complete server crash that ended the session (fixed now) and I got some pointers on what to improve - but overall there was some fun to be head for a few minutes.

For the play test today I had finally implemented character levels - it really helps to have something to achieve.
The animation for it is a little rushed, but I guess it works for now:

lvlup.gif

Levelups heal you to full health and give you more damage, more heals more skills and more everything ;)

As I mentioned I had "improved" my todo list by adding two more skills (when removing the meele attack for both caster classes).

Here is the most boring gameplay gif so far:

hot.gif

That shows a warrior doing nothing (and getting hit) while he is healed by a "high level" heal over time - which is the new healer skill.
And yes, if you login hundreds of times into your own game, you end up with "asdf" as your name. No way around it.

While play testing both mages complained about the missing last skill, but I got that done tonight too, it's the skill "firestorm" and here it is in action:

firestorm.gif

While adding the firestorm, I nearly exploded myself, when it took me 15 minutes to rotate my fireballs correctly... I guess the deadline is getting to me.

 

And lastly I managed to wrestle the IE into compliance regarding a cursor issue - IE doesn't like png files as the cursor. So you have to create a "cur" file and add a style for ie:

This is the page I used to create my "cur" file: http://www.cursor.cc/

And this is the css to include it that seems to work on ie/firefox/chrome/edge:

cursor: url("data/icons/cursor.cur"), auto; /* IE */
cursor: url("data/icons/cursor.png") 0 0, auto; /* Chrome, Firefox*/

That's it for this update - I really hope it will be fun to play together.

In reply to Deltakosh: I understood that you just though it was funny, not making fun of me - my response wasn't worded correctly.
I am still mind boggled by the todo babylonJS is surely generating :)

Link to comment
Share on other sites

wow! You've done what I have always wanted to do, but I've no idea how. Awesome work!

Any advice on how to get started building the client-server communication? Are you using any game server engine or coding everything on your own? Apologies if already asked/answered this and I have missed it.

 

Cheers,

Javier

Link to comment
Share on other sites

Hi everyone,

So it's down to the last hours of the challenge.

Yesterday I implemented something that wasn't planned but that I got as feedback from play testing at lunch at work:

emote.gif

The available emotes are:
/cheer
/dance
/wave
/bow

And today I implemented combat texts:

combattext.gif

Incoming damage, damage you deal and heals are displayed as floating numbers.
There are also options to disable those.

It's done with canvas2d and a projects from 3d coordinates to screen coordinates.
(I couldn't use track node, as I am doing with the name plates, because the numbers should stay static on screen and now follow you or the enemies around - which track nodes would do.)

Here are the three lines that make it possible:

let coords = BABYLON.Vector3.Project(this.pos, BABYLON.Matrix.Identity(), scene.getTransformMatrix(),
    scene.activeCamera.viewport.toGlobal(scene.getEngine().getRenderWidth(), scene.getEngine().getRenderHeight()));

this.text.x = coords.x - this.text.width / 2 + xOffset;
this.text.y = this.text.parent.height - coords.y; //canvas2D starts y coordinates 0 on the bottom

The transform code in the first line is from an older thread on this board - as always a useful resource (only the parameters to toGlobal had changed since the old posting).
The second line centers the text by subtracting half the width - easy, I know.
And the third line nearly canceled the whole combat text implementation.. I forgot for the longest time, that canvas2D has 0, 0 on the LOWER left corner of the screen.
Tracking on the x-axis was perfect.. but everything on the y-axis went crazy as soon as the camera moved as long as I was setting text.y = coords.y.

I have also introduces mob levels and different textures for higher level slimes.

level.png

Not too impressive, but at least you can tell they are different from each other and you maybe want to avoid them until you have the same level or bring friends.

I hope I didn't over tune the boss monsters... but we will see if any group of players manages to kill them.
Spoiler: Nobody will be able to solo them. (Well, maybe if you find an exploit :) )

Thanks to another play testing session with my friend Kenny I found a a cookie issue and an aggro issue.
All cookies were just set for the current session, so you lost your progress when closing the browser.
Now they stay for a while. (10 years should be enough, right?)
And the aggro issue had to do with monsters always attacking the closest player - this is fixed now, they now react to the amount of damage & healing that has been done.

 

@Javierl

First of all thank you for the praise :)

3 hours ago, Javierl said:

Any advice on how to get started building the client-server communication? Are you using any game server engine or coding everything on your own? Apologies if already asked/answered this and I have missed it.

I am not sure, if I am in a good position to give advice on the client-server communication - but I will try.

Only listen if it's just a personal fun project for you, because that is what this is for me. This lets me get away with just experimenting and keeping things that seem to work.

I am using these frameworks: BabylonJS & Canvas2D on the client side, and "fs", "ws" and "xml2js" on the server side.

This means, that my server client communication is pure websocket (which means people behind stupid or mean proxies/firewalls can't play).
Also I didn't do any research on the communication side of things other then checking out simple echo demos for websockets.

What I started with and what I would advise you to start with the absolut basics:

Look for a simple server side node script that accepts websocket connections.
Write a gameloop into that script that calls a functions every x milliseconds. (You can start with a simple setInterval every 20 ms. - note that this doesn't give you constants 20ms steps, so you will want to improve on that later, one solution is posted here: http://www.html5gamedevs.com/profile/22713-raggar/)

Then use a simple object that contains an id, a position and create a few of those on the server side.

In the gameloop convert the whole array to JSON and send it to all clients.

On the clientside take what the server sends you, convert it back to objects and use those to create/update game objects that you can display with babylonJS.

Then have the client issue commands for one of the objects (doing nothing on the client side but to tell the server about the command) the server then can move the object accordingly and tell everyone about it.

Two more things: I implemented a "changed" flag on my server-objects so only objects that actually changed are send to all clients. And I don't send X,Y changed on my objects to the clients every frame. Instead the clients and the server know the speed and the target for the object (information is only send when the target/speed changes) so objects move on the client and server in parallel without the need for messages every frame.

The stuff the server sends to all clients gets more and more.. my message now contains stuff like "effects", "combatInfo", "actions", "emotes", "chat" and more. But only ever what is needed/changed right now.

I hope that's enough to get you started :)

Link to comment
Share on other sites

@Javierl Idk how jp is doing the server/client side, but i guess it's something like this

var dataToSend = {
	type: "auth",
	data: {
		username: "testusername",
		password: "testpassword"
	}
}

JSON.stringify that and send via websocket. 

Now on server side check if receivedData.type = "auth" then you call function auth(receivedData.data) and so on. Don't forget to JSON.parse(receivedData) :D

 

@jpdev Impresive work, can't wait for the sources, i guess i have a lot to learn from them

Link to comment
Share on other sites

On 28.2. I uploaded my project - I am now just waiting for the challenge to come to it's presentation time.

While the game is pretty much in exactly the state I wanted it to be at the end of the challenge, I am still thinking about expanding it and continue playing around with it - simply because it's fun to do, and I think (yes, I am biased) also fun to play with friends.

For example I am playing around in blender for more content - but I am not sure about the latest creation:

Disclaimer: This will not be part of the challenge version - so don't go looking for him or it or whatever :)

hop.gifdie.gifrun.gif

Yes, I noticed the tail looks a bit weird - I found "limited desolve" in blender (great tool) but I think i might have overdone it.

@csganja I am not convinced the sources will really be something to learn from - I can only say it again: I was (and still am) just messily experimenting away (not following any best practice or anything, simply because I just went ahead and implemented things how I think they might work :) ) - still they might be of some value just to see how it can be done (but not how it should be done ;)).

 

Link to comment
Share on other sites

Since the challenge has officially started, here is the link to the game:

http://rpg.jppresents.net

Some information before you start:

This is a rpg game where you control a character of one of the three classes:

Fighter - meele fighters can take a punch and also deliver one
Healer - pure magic healers that can't fight themselfs but are valueable in keeping everyone alive
Caster - ranged magic damage dealer that control fire

You choose a name for your character and the class on login.
You can change your class by reloading the game in your browser.

You can move by left clicking anywhere on the ground.
You can use skills by clicking them in the skillbar or pressing the corresponding number.
Target other player or monsters by clicking on them or their nameplate.
You can click the text field in the lower left corner or press "Return" to begin typing a message to everybody else, another "Return" sends the message.

You can gain up to 5 levels by gathering xp by killing monsters or by healing other players who are killing monsters.
Each level gives you more hp, more damage/bigger heals and most levels give you new abilities.

And here is the link to the challenge: 

 

I hope you have a look and vote for me if you like it.

Also please let me know about any bugs or problems you encounter!

Link to comment
Share on other sites

  • 6 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...