-
The story
06/17/2020 at 18:37 • 0 commentsThe game needs a story. Something that has been lacking in Star Trek for more then a decade now, not taking into account some star trek online narratives and of course the odd quality fan-fic. But this isn't a straight Star Trek story, it is a parody that takes aim at the current iteration of terribly write nonsense Trek caused by overrated writers and directors like JarJar Abrams and Alex Kurtzman. So the "levels" in the game should address themes on faults in modern Trek as committed by that cabal of gimmicky mediocrity.
The format for the game is pretty simple. Although the current writers would not understand such a structure, the game has a beginnings, middles and an endings. This structure will be used for the overall structure as well as the levels.
A level will have an introduction where a new character can enter and a new foe can appear. Then the middle of the level will be a strategic battle with the current enemy. A level boss will typically end the level, resulting is a completed arc as it should be! The overall narrative also should have some of this structure.
Level 1 : Introduction.
This level will set up the story and contain a training level to get used to the controls. When the backstory is established, some characters are introduces such as Nog and the Gorn, a simulation of the Jem'Hadar ships will train the player in using the phasers. When this is completed, the conclusion to this level will be the Defiant going to pick up Jake Sisko.
Level 2 : Illogical
Arriving at Risa, the Defiant picks up Jake Sisko. As a successful writer, his talents will be welcome on the coming adventure.
-
Playable Demo 1
04/29/2020 at 10:36 • 0 commentsFor testing purposes, I present the first playable demo. Clickerty!
Controls are :
AWSD for moving The Defiant
Arrow keys for moving the crosshair
Space to fire phasers
I have only tested in Firefox, so mileage may vary. There are of course many bugs and quirks. For instance, pressing any of the controls before the actual game starts may crash the engine.I'm looking for feedback on how this particular game mechanic does or should work. Is it too hard or too easy. What is missing? What needs tweaking. All that sort of good stuff
This isn't the game proper which will be guided by a narrative. This is just a simple scene setup to get some feedback
-
Small update
04/28/2020 at 19:21 • 0 commentsAfter the small headache that was the collision detection function, I took it a bit slower. I havn't got a lot to show but for a small implementation of a game mechanic I talked about in the last log. In the demo you see the phaser power level. The phaser stops when the "energy bank" is depleted. Another mechanic is that when below 50% power, the phaser can not fire until it is over 50%. This means you have to be tactical on when and how long you can fire.
-
Hit and miss
04/26/2020 at 15:52 • 0 commentsI've been thinking about the game mechanics a bit and I'm thinking of making the action bits a bit more straight forward. Just shoot some stuff with various weapons and have the dialogue between those sessions.
But for it to work, you have to accurately be able to shoot something. So I need some methods to determine if something is hit by a phaser or something else. Some collision detection and such.
All the previous demo's with the phaser fire were faked. There was no function to see if the beam actually hit something, but the demo today shows the phaser to be highly accurate. It detects hits on a per pixel level, which is what I wanted. Unfortunately the current method is NOT the one I wanted.
My initial idea was to simply take the screen position, reverse transform and scale that pixel one time per object and then check if that pixel would exist an if it did, if it had the alpha channel on or not. If not, it would be a hit.
However, after tinkering and thinking about it for a while, I could not get it to work. So I brute forced it and put it in the drawing routine. This does make for a bit of a performance hit and it will limit the number of on screen actors. What I do now is to set a target attribute which, when it is true, will make the drawing routine check if the pixel that is being drawn matches a pixel of a weapon system. If it does, it sets a hit flag for that object and as the object function is executed in the same loop, it will know each frame if the ship is being hit or not.
It is not elegant, but it works. I also build it so that when you fire the phaser, you can't control the cross-hair. This is part of the mechanics I'm playing with. There are a number of constraints I want to have to make the game part more challenging and interesting. The phaser-lock feature is the first. It makes it so you have to plan your attack because while you can't directly steer the cross-hair while firing, when you move the ship, the cross-hair is influenced by that. So by planning your angle of attack, you can then move you ship accordingly while firing and land more hits.
Another constraint I'm thinking about is to limit the phaser itself. This could be done in a variety of ways. There could be a cool-down time, limiting the speed at which you can fire or a energy bank that, when depleted renders the weapon useless for some time. A combination could also be possible, but effectively I want the player to have to think about tactics on how to approach the enemy.
I hope that I'll be able to implement my original more elegant solution for hit-detection, but for now this seems to work fine.
Update : I really did not like my solution. It was wasteful and and it did not belong in the render engine code. I did not want to check every point against another point especially not at that point in time. So I doubled down on the other solution and it seems I have it working.It is far more elegant and useful. The function takes the cross hair coordinates, reverse transforms it with the translation, rotation and scale data and computes if that point lies within the graphic asset and if it does, it checks if that point has alpha or not. If it does not, you just hit the ship!
I have got it to the point where it requires no matrix transformations at all and, per coordinate is very light weight.
Here is a fun screenshot.
This is a test image to see what the hit function was actually seeing. This test function is tremendously slow, but it does show that the reverse transform makes for a very accurate mapping to the source graphic.
The exercise in thinking about this problem has been interesting. My frustrated quick ugly solution did the same job and per pixel was quite light weight. This solution per pixel is really compute heavy, but I need only to compute one, not thousands.
In effect this means that for collision detection between any point to any object, the time needed to calculate would be roughly the time that is needed to scale and rotate any pixel of an active object.
Here is the function as it stands now.function chkHit(objID,px,py){ // check a screen coordinate against an object. Used for collision detection and weapons. var hit = false; const deg = IGObjects[objID]["rotate"], scale = IGObjects[objID]["scale"], tileID = assetPointer[IGObjects[objID]["mediaObject"]], tileWidth = Math.floor(sceneGraphics[tileID].width * scale), tileHeight = Math.floor(sceneGraphics[tileID].height * scale), centerX = Math.round(tileWidth / 2), centerY = Math.round(tileHeight / 2); // needed for full 360 rotation with shear transforms. if (deg > 270){ deg -= 360; } if (deg < 90){ var rad = deg2rad(deg); } else { var rad = -deg2rad(180 - deg); } const aShear = -Math.tan(rad/2).toFixed(2), bShear = Math.sin(rad).toFixed(2); // shear transform just the center var xDisplace = centerX + (aShear * centerY), yDisplace = centerY + Math.floor(bShear * xDisplace); xDisplace += Math.floor(aShear * yDisplace); const xDiff = centerX - xDisplace,// get the xoffset difference yDiff = centerY - yDisplace;// get the yoffset difference var dx = px - IGObjects[objID]["x"]; var dy = py - IGObjects[objID]["y"]; if (deg >= 90 && deg <= 270){ // mirror the shear rotation on both axis for full rotation & set pivot point. dx = (dx * -1) + xDiff; dy = (dy * -1) + yDiff; } else { // set pivot point for the other half dx -= xDiff - tileWidth; dy -= yDiff - tileHeight - 2; } dx -= aShear * dy * 2; // reverse transform dy -= bShear * dx; // the coordinate. dx = Math.floor(dx / scale); // account for scaling dy = Math.floor(dy / scale); if (dx > 0 && dy > 0 && dx < sceneGraphics[tileID].width && dy < sceneGraphics[tileID].height){ // coordinates fall within the graphics boundaries var curPixel = (dy * sceneGraphics[tileID].width + dx) * 4; if (sceneGraphics[tileID].data[curPixel + 3] != 0){ // Pixel has no alpha. This is a hit. hit = true; } } return hit; }
Perhaps the most interesting thing here is the reverse shear rotation method with is very simple indeed. The rest of it is really just the reverse of any odd choice I made earlier for the sprite rendering routine.
But anyway, now I can finally sleep! -
Action and Drama
04/21/2020 at 13:07 • 0 commentsI have been spending a lot of time building up the storytelling elements of the game by using the stuff I build in my adventure engine project, but half of this game is action, not drama! The interactive stuff until now basically was the stuff I did in the "asteroids" engine. So it was time to actually start working on the action game play proper.
I started an NPC lib, which may be poorly named as it is entirely possible that player function will also be stashed away there, but for now, the name applies! This library does the collision detection, NPC actions and manages the on screen assets.
In the following short demo, you can see how the Defiant is firing its phasers on a Jem Hadar ship. When hit, the shields will show, but they will also weaken. When the shield is gone, the ship explodes.
The methodology is pretty straight forward. When the enemy ship is spawned, it gets it's attributes and a starter function. This function sets the attributes like shield and strength. Finally it attaches the relevant NPC function to the active object, which means that every loop, this function will be executed.
It is the NCP function that checks for its own damage and subtracts the "points". When the shield reaches zero, the media object for the ship is altered to the explosion sprite and the attached function is set to the explosion function, which will play the sound, animate the KaBooooOOOom for 15 frames/cycles and then set the object inactive so it will be invisible and not have it's function called.
The in game object can now be reused for a new enemy. The number of in game objects like this can be anything but for now it is just 1. These are defined in advance in the game script.
The next thing to do is to build some gauges to see the shield and hull strength for the Defiant and perhaps the enemy ship, tweak the game play, add some more weapons and enemies and call it a workable demo which I'll be putting online for all to try out.
In advance.. it will be buggy! And now... CARNAGE!
-
Setting phasers to fun
04/20/2020 at 23:13 • 0 commentsWith Corona going on, real work as pretty much dried up so I find I have oodles to time to mess around and my current favourite activity is getting this game concept to a new level, well new for me.
Anybody familiar with my other hobby projects may know that I often lose sight of goals and get distracted by minutia. Well, while this might very well be the case here, the fact that I can rapidly add and alter my carefully crafted set of code libraries means that now I can perhaps get A. bogged down in details and B. still have something real to show for it.
Case in point, after tinkering on and off with the system and swiping some graphics from the intarwebs for assets, I got pretty close to the way I want to start the game and how it should feel.
From the very first game screen, I want the game to never leave "space" It should always feel like the player is either travelling or arriving somewhere. The entire game should in essence be one continues shot from beginning to end.
This is how I thing the game could start.
I'm still not happy with the tween function which is defined in steps not time, but I managed to script around this shortcoming and I will address it later. For now the main goal is to rough it out.
-
Fast pace development
04/20/2020 at 15:37 • 0 commentsThe time and effort I put into build my arsenal of methods for game structure and thinking in terms of game machines are really paying off in this project. The scripting and compositing functions make it a breeze to implement functionality without much breakage or logic bombs.
I have been adding to and removing from the adventure script "language", some of which will find their way back to the other engines I'm sure. I have added waitForInput, JS function calls, labels, direct dialogue functions and a tween command that I'm not 100% happy with.
Apart from the "action logic", most of the game can be written in this form. Lets see a demo of the current state of affairs and then look at the script that drives it.
After some short splash graphics, the introduction text is displayed. These text/dialogue functions set the system in a waitForInput state. This means that the script interpreter stops at that line and only continues after any button is pressed.
After user input, the script continues. More assets are activated and Captain Nog has some things to say. There is a "goto" label test (Yes, I have included the evil that is goto) and then all game assets are in place and can be controlled by either keyboard or joypad.
Here is an annotated version of the script.
main // Define the in game object def logo mediaObject=logo;x=260;y=140; def planet mediaObject=earth;x=410;y=202;rotate=20;scale=1;scatter=50 def crosshair mediaObject=crosshair;x=200;y=130;active=false def defiant1 mediaObject=defiant1;x=200;y=190;scale=.4;active=false def gui mediaObject=LCARS1;x=2;y=2;active=true;layer=gui;active=false def textBox mediaObject=TextBoxBuff;x=20;y=5;layer=gui def dialog mediaObject=DialogBoxBuff;x=39;y=22;layer=gui def nog mediaObject=nog;x=324;y=202;frameCount=3 label intro exec warpSpeed=1 //execute a JS function set logo scatter=100; set logo active=true; play transporter tween logo scatter=0@-1 wait 5 set logo active=false; wait 1 label game textbox Intoduction "The year 2400. 25 years after the ending of the dominion war. In order to celebrate this event after a quater of a century, there is a symposium planned on Bajor The historical ship The Defiant has been refubished in space dock for the event and has been handed to Captain Nog who will pick up some of the old crew from DS9" set textBox active=false exec warpSpeed=0 set planet active=true tween planet scatter=0@-1 wait 5 set gui active=true set defiant1 active=true wait 2 play soundfx1 charSay nog "Lets see what this old wardog has got left. Start reenactment pattern delta" play soundfx1 charSay nog "this is a wait for input test" endDialog nog goto test break // without the goto test, this would stop the script label test play soundfx1 charSay nog "We jumped to a label" endDialog nog set crosshair active=true break
There is a fair bit going on here and if you read the piece on the HTML5 adventure engine scripting log, then you might see some familiar and some new stuff.
The main difference is the "def" command. This command simply defines a "thing" to be used in game. It can be a GUI element, a NPC, a planet or the ship itself. These elements can have their own functions. They are processed in the order they are defined.
The "tween" function at this moment can tween multiple numerical values by setting a target and a step. This is less then ideal for various reasons so I intend to rewrite this so it can be timed by frames.
"Exec" starts a JS function. This way I can control the actual game code from the script. The "label" and "goto" command speak for themselves and the "textBox" and "charSay" control the methods to display text context.
The "endDialog" statement is simply a lazy helper function so the code remains cleaner. I suspect a lot more of these statements will appear as elements become more complex.
I'm especially chuffed with the textbox functionality. It fits neatly and effortlessly in the game mechanics.
-
Game mechanics
04/19/2020 at 22:14 • 0 commentsWhile this game is mostly build on the adventure engine, I plan for it to be mostly an action type game with comedic interludes that make fun of Star Trek and provide some commentary.
I did some work on adapting the scripting engine for the game which is going quite well, but I felt it was also nessesary to focus on the actual game mechanics. So I rigged up a steerable ship and crosshair and mapped their movements to the keyboard and gamepad.
Eventually It will be a dodge and shoot game where you can use the crosshair to lock on to a target and fire phasers or torpedoes.
In this demo you see a bit of the scripting engine test and the firing mechanics.