Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Faux Car  (Read 15169 times)

0 Members and 1 Guest are viewing this topic.

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4328
    • View Profile
    • Email
Re: Faux Car
« Reply #30 on: May 02, 2016, 05:28:44 pm »
racing against trees... why not after all!  ;D
SFML / OS X developer

Mortal

  • Full Member
  • ***
  • Posts: 248
    • View Profile
Re: Faux Car
« Reply #31 on: May 03, 2016, 12:10:01 am »
hehe, trees is so hilarious

the video on your youtube channel is much more better. i enjoyed it and wished if the track is longer.

Hapax

  • Hero Member
  • *****
  • Posts: 2789
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Faux Car
« Reply #32 on: May 03, 2016, 12:47:36 am »
The reason that the opponents are trees/bushes is because they have/had to be drawn as part of the same vertex array as the track (including roadside objects) itself so uses the same texture. Technically, the opponents are actually roadside objects that are just moved!

I'm adding the ability to keep track of road heights so that objects drawn after the track can be clipped by the correct amount for its distance so that they can be "slotted in" to the scenery. This will release the restraint that everything should be drawn with a single vertex array other than the static single sprite player.

I have so many things that I want to add to this that none of them ever get added :( Still, I'm currently working on just the track so when I post newer track stuff, I'll leave the playable version (v0.1.0) available for download (there is no car in the newer version as yet - it's all definition, drawing and camera work)
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Hapax

  • Hero Member
  • *****
  • Posts: 2789
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Faux Car
« Reply #33 on: May 17, 2016, 04:55:22 pm »
Latest update with new video!

It's at v0.2.5 at the moment.
It's all track definition, display and camera work.
Still, just because there is no longer a player sprite, driving controls, score, opponents, roadside objects with textures or sound doesn't mean that there hasn't been progress and there aren't new things!

The track definition can now have a palette of roadmarks. That is, roadmark for a single segment of track. They can then be "painted" onto the track and re-used (every segment uses one from the palette or nothing).

"Extra" roadmarks are also possible that aren't stored in the palette and are just additional "one-shot" marks. These can actually be added in real-time and I currently add "skid marks" to the track by pressing a key (I forgot to do this for the video). They can only be added though; once they're there, they're there. Well, you can remove them but it's not simple to find them and removing them could cause relocation of data.

Split-screen has been integrated with the way the track's view is now used and there are now three pre-defined "screens": one vierw full, two view top, two view bottom. The two views can be completely independant parts of the track but the camera needs to be set for each view. The top one in the video (first-person-style) is a customised view that allows the camera to get in closer to bring out more feeling of speed and being closer to the road.

Probably the most noticable thing in the video will be the new objects. They are technically identical to the road marks (they're just quads linearly interpolated between segments) but also allow height. Objects, like roadmarks, are stored in a palette and can be added like "extra roadmarks" in that they can be "painted/pasted" wherever on the track. Each object can have a number of parts or "planes", which are just quads. These planes are stored withing a single segment and grouped into objects. Objects in the palette can be re-used in any position ("depth" cannot be changed - it is always in the same depth within a segment) with a colour that is multiplied by each plane. Planes are not sorted depending on distance from the camera; they are only drawn in the order provided so actual depth sorting is not (currently?) possible. It is possible to see this in the video; the "solid chevrons" near the beginning of the track have the left side drawn first so when they are close, the right ones are drawn incorrectly.

Another noticable thing (if you watch more than the first minute of the video) is that the camera not has completely free movement. Its only real positional restraint is that it is relative to the track (since the curves in the road are "fake/pseudo"). Camera rotation, though, is more limited, as expected. The only rotation provided by the ability to move the vanishing point to any position. I have considered and may add z rotation at a later date (it should be simple view rotation).

Selba Ward's Progress Bar is used at the top to show the current position in the track. It's left at its default state so it's a simple black and white bar. Not that it's currently necessary since there is also a single roadmark that stretches the entire length of the road and starts from the left side of the road and ends at the right side.

Although the road and roadmarks are stored with direct segment information, the track is built from a "blueprint". This blueprint specifies certain higher-level properties and then the track definition is built from that blueprint. For example, the blueprint's road definition (actual road, not marks, colours or objects) is randomly generated - similar to how it was in v0.1.0. It randomly chooses the properties of each piece of road such as length and bend amounts (start bend and end bend). Each piece always starts with the bend amount of the previous piece to allow smooth joints. When building from the blueprint, these amounts are interpolated using an easing function that generates smooth turns in the road. The altitude is similarly generated with the final tilt angle always being zero so that the road is flat at the end. The altitudes usually finish before the road ends, which is why the road is often flat later on.

Roadmarks are also specified in the blueprint. This allows "extra roadmarks" to be defined overall rather than segment by segment. For example, the "progress roadmark" is defined in the blueprint as a single quad the starts at the first segment at the left of the road and ends at the last segment at the right of the road. When the definition is built from the blueprint, this is interpolated for each segment and each segment gets an extra roadmark that is contained in that single segment.

Plinth is used extensively in Faux Car. From just specifying colours from the extended colour list through using its vectors on to using its interpolations. The interpolations form most of the work in the track calculations. That is linear mostly but the easing interpolation (smoothing track pieces) as well as piecewise interpolation (the "rainbow block" at the beginning) are also used along with its Range type with "inverse linear" interpolation. Plinth is also used for resource management although there aren't many of those at this point.

How the track's road works
The centre point (the front) of the segments are projected towards the vanishing point. The amount of bend for that segment is added to that segment and that value is stored. Each segment backwards takes the total bend so far and adds on its own and offsets its segment point by that amount; it's accumulative. For each of these points, a single unit is measured at its depth and also stored; this serves as a multiplying amount for anything at that depth, including the "bend" (or accumulated horizontal offset) amount.

After these points have been projected, the actual vertices are updated. These are done in reverse so that the front of the track is drawn over the back. Each segment has a stored projected position and a "unit length" so any point within one segment (between two segment points) can be interpolated and offset from the point by multiplying by the unit length. This applies to the road, the roadmarks, and the objects! The only thing that isn't subject to this is the road-side which is always from the left-side of the view to the right-side of the view; it's y position is taken from the segment points but the x positions are always the same.

Anyway, enough waffling; here's the video:
http://www.youtube.com/watch?v=ceuQimdKSuM
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

AFS

  • Full Member
  • ***
  • Posts: 115
    • View Profile
Re: Faux Car
« Reply #34 on: May 17, 2016, 08:52:15 pm »
Impressive stuff! (although I must admit that half of your explanation went over my head :P).

I remember these kind of racing games used simple sprites as background (buildings, clouds and whatnot), and they just moved left and right according to the camera. Very effective to add depth. Are you planning on adding those?

Hapax

  • Hero Member
  • *****
  • Posts: 2789
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Faux Car
« Reply #35 on: May 17, 2016, 10:29:16 pm »
Thank you!  :)

Yes, I am planning to add image/texture-based stuff too. The earlier, playable version -
- did have a sprite for the player, "billboard" style textured road-side objects, bitmap text and a wrapped background image at the horizon, which I intend to re-implement once the track stuff is further on. Knowing me, though, I'll probably start to add it before it's ready, as I did before. ;D
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Faux Car
« Reply #36 on: May 18, 2016, 02:05:42 pm »
This looks awesome! Reminds me of the good old days with Lotus Turbo Challenge :)
I'm looking forward to a native linux version ;-)
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Rhimlock

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Faux Car
« Reply #37 on: May 20, 2016, 01:49:33 pm »
Nice.
Makes me want to chase some trees, who think they could run away from me ;-)

Hapax

  • Hero Member
  • *****
  • Posts: 2789
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Faux Car
« Reply #38 on: January 31, 2017, 03:35:40 am »
Still working on this, on and off.
Current version: 0.3.2

Fully remade the "track" engine.
Technically, it's now called "scene" as it's the entire scene :)

Prepare yourself for a lot of information!
(there is a screenshot at the end)


The entire thing is split into "projects" (I'm using Visual Studio). This allows me to do all of the scene work in one and build it as a static library. Then, it can be used by multiple other projects. For example, the actual game and a track editor (which still needs to be made).

I'll be mainly discussing the "Scene" project/library here as that's the bit I've been working on (and is the "interesting" part as there's no game or anything yet).

The Scene class is the actual drawable scene and is the thing that does all the projections and putting everything together. It holds a pointer to scene definition classes so that they can be switched out (separately, if required).
The scene definition classes are:
Track, Marks, Objects and Sprites.

Track is the road, mainly.
That is, it defines its length, its curves and hills, its colours as well the horizon/sky/background textures to use.
A track is defined by "pieces". There are two types of pieces: Standard and Pattern. Most pieces are Standard.
Standard piece is a basic, singular piece that occurs only once. A pattern piece allows a repeatable pattern to be created.
Track stores these pieces and Scene interpolates the points it needs from the pieces as it needs them.

A StandardPiece stores a position (start distance along track), a length (distance from position), and then an initial and final value. The value is determined by the type of StandardPiece. The start value is used at the beginning of the piece (at its position) and the final value is used at the end of the piece (position + length). At any distance between those two distances, the value is interpolated. The interpolation type can be specified for each piece. Types are: none, linear and ease. Linear and Ease interpolate the start and final value based on linear and easing interpolation. None ignore the final value and uses only the start value.

The two most obvious and most important are bendPieces and slopePieces. These define the curves and hills of the track. They are both of type StandardPiece.
For the following examples, we will assume that the piece's position is 100 and its length is 100. This piece would then be in effect from 100 up to 200.
Examples of bend pieces:
A curve could have an initial value of 0.2 (a slight curve to the right). The curve would have interpolation of None and any final value is not used. This creates a simple, constant curve (all points on this piece would be a bend value of 0.2)
A curve could have an initial value of 0.2 (slight curve to the right) and a final value of 0 (straight ahead). The curve would have a bend value of 0.2 at distance 100, a value of 0 at distance 200 and a value of 0.1 at distance 150. This type connects a right bend (of 0.2) to a straight road (0).
Examples of slope pieces:
A hill could have an initial value of 0.2 (slight incline). The hill would have interpolation of None and any final value is not used. This creates a simple, constant incline (all points on this piece would be a slope value of 0.2)
A hill could have an initial value of 0.2 (slight incline) and a final value of 0 (flat). The hill would have a slope value of 0.2 at distance 100, a value of 0 at distance 200 and value of 0.1 at distance 150. This type connects an incline (of 0.2) to a flat road (0).

Similar pieces exist for the colour of the road, the colour of the ground (roadside), the colours of the ground on the background and the colours in the sky gradient, and even the texture IDs of the sky, ground (background), and reverse sky and ground (this can be used to change these colours and textures dependant on distance on the track).

A Pattern Piece is slightly more complex.
It has a (start) position as with StandardPiece. It also has the interpolation type.
However, instead of a single initial value and a single final value, it has a vector for each. It then stores a vector of "nodes", which basically just store which value from the vectors to use and how long for. The piece also stores how many types the entire pattern of nodes should be repeated. The length of this piece, then, is one higher than the number of repeats, multiplied by the length of all of the nodes.
The PatternPiece is used for road and ground (roadside) colours. This allows repeating colour patterns including the simple alternating shades as per the "usual" road-based game.

Using these pieces, a track can be built simply and Scene can create the final track image from that. Bend and Slope pieces can overlap; the values are simply added together where multiple pieces overlap.

Marks are the marks on the road (or anywhere on the ground).
A Mark is defined as one or more Quads. These quads are two-dimensional as they are flat on the road.
Each mark has its own position, colour and scale, which applies to all quads in that mark.
Each quad stores the four points of a quad - a polygon with four vertices, as well its own colour and an positional offset. The polygon must be convex but, of course, concave polygons can be created by using multiple quads.
Quads are stored separately (in their own vector) and the Marks store a vector of pointers to quads. This allows the same quads to be used in different marks.
Marks, when drawn, are clipped to each segment of the road and drawn in pieces, one or two per segment that contains it. For example, a simple stripe that stretches for 6 segments will be split into 6 stripes - one for each segment.
Marks and Quads are stored in their original form. They are split in real-time each frame. This, however, can be time-consuming so Marks can be "baked". Baking splits all of the marks' quads and stores the split quads and which segment it should be displayed with. This allows much quicker calculations.

Objects are very similar to Marks. They also store multiple quads, which are split for each segment. They also allow baking. The only real difference is that the quads in Objects are three-dimensional. That is, they can also have height/vertical offset (y) whereas Marks can only have horizontal offset (x) and distance (z).

Sprites are also quite similar to both Marks and Objects but are a lot more simple. They are "billboard" quads that are specified by width and height only. However, their position is three-dimensional, allowing "floating" sprites. Sprites do have one feature that objects and marks do not - textures.
Sprites are used for all 2D textured sprite graphics in the scene. They can be static (roadside scenery etc.) or dynamic (vehicles etc.).
Sprites does not contain only the Scene Sprites described above; it also includes Sky Sprites that allow sprites to be drawn on the background as it anchors to the background "plate". They are always drawn after all of the background and before all of the scene (track, marks, objects and scene sprites).

There can be a lot of Marks, Objects and Sprites for a track so each cycle, a vector of pointers of each are prepared; these pointers are all of the items that are within the visible range of the scene. Then, for each segment, the vector of pointers is then consulted to see which ones are in that segment. This significantly reduces the amount of testing.

The Scene itself only really has camera controls plus a few set-up things. The set-up things are, of course, setting which Track, Marks, Objects and Sprites to use as well as setting which texture resources to use. There are two textures: the main scene texture and the background texture. It also stores a TextureSheet for each, which is basically just the texture rects for each sprite/image in the texture.
There is also a function to get a predefined view, which provides a full window view or half window views in the top or bottom half - useful for one player and two player set-ups!
The rest of the controls are camera controls. Things like: position (3D), aspect ratio, where the vanishing point is, the camera depth (effective depth of the scene) - I think I will use this as an effect :).
One other feature added to this version is reversible direction. That is, the track can be drawn from the camera as if it's facing towards the beginning of the track instead of the end. One use for this is a flipped view to display a mirror.
Of course, there is one other method: update(), which brings Scene up to date based on its camera's current position and using the current state of the Track, Marks, Objects and Sprites.

Scene's update sets the range of segments that will be drawn and then updates the projections for each. It then updates the background vertex array before updating the main scene vertex array.

The background vertex array consists of multiple quads:
the sky base (skyTopColor),
the sky gradient - top part (skyTopColor to skyMiddleColor),
the sky gradient - bottom part (skyMiddleColor to skyBottomColor),
the skyline - texture above horizon,
the ground block (groundBlockColor - colour below horizon),
the groundline - texture below horizon,
all Sky Sprites.

The Scene vertex array consists of, for each segment:
a ground segment (both road sides at once - a horizontal bar),
a road segment,
all baked marks' quads for the segment,
all unbaked marks' quads clipped to the segment,
all baked objects' quads for the segment,
all unbaked objects' quads clipped to the segment,
all sprites within the segment.

First, it calculates a maximum number of vertices required to draw the scene.
It starts with the number of segment multiplied by 8 (one quad for the ground and one quad for the road)
It sets the range of Marks, Objects and Sprites so that they can prepare the ones in range and then adds 4 for each of their quad in the segment.
Note that, at this point, any unbaked Marks or Objects will be split into segments and stored as quads - similar to baked quads.
During the projection updates earlier, if a segment is facing away from the camera, it marks it as invisible and adds 8 (4 for the ground, 4 for the road) to a counter called vertexReduction, as these won't be drawn.
The vertex array is then resized to the maximum number of vertices required minus vertexReduction.

vertexReduction is reset to 0 as there may be more reductions to follow...

Then, quads are added...
For each segment - in reverse order (see Painter's Algorithm):
if the segment was not previously as invisible, the ground and road quads are added,
loops through all baked marks' quads within visible range to see if they're for the current segment. If it is, it will add that quad otherwise it will add 4 to vertexReduction,
similarly loops through all marks' dynamically split quads and adds quads or 4 to vertexReduction,
loops through all baked objects' quads within visible range to see if they're for the current segment. If it is, it will add the quad only the top of the quad is above the top of the hill/ground at this point otherwise it will add 4 to vertexReduction,
similarly loops through all objects' dynamically split quads and adds quads or 4 to vertexReduction if behind a hill,
loops through all sprites in range to see which ones are in the current segment. For each one that is, if the sprite's boolean "isActive" is true, the sprite's quad will be added unless its position is on the wrong side of the camera or its top is below the hill in which case 4 will be added to vertexReduction. If isActive is false, vertexReduction gets another 4.

"Adding a quad" in this case consists of using an iterator pointing to the vertex array (technically, it's a vector of vertices) and modifying the current and following 3 vertices for the quad and then moving the iterator forward by four. When a quad that was prepared for doesn't get added, this leaves unused vertices at the end of the vertex array. vertexReduction keeps track of how many are unused.

That's the update. All that is left is to set the view to whichever is needed and the draw it. The draw function draws the background vertex array first using the background texture and then draws the scene vertex array using the scene texture. When it draws the scene "vector" of vertices, it uses the pointer overload for draw that takes a size and passes the size of the vector minus vertexReduction, which stops it from drawing all the unused vertices at the end:
target.draw(m_vertices.data(), m_vertices.size() - m_vertexReduction, primitiveType, states);



The app itself that I am currently using to develop the Scene will be a starting point for both the game and the track editor. Currently, it allows movement of the camera, independant movement of the single car sprite including flipping its direction, modification of the camera depth and vanishing point, and changing setup things like: toggling camera direction, car visibility, framerate limit, pixelation and cycling window mode (window, fullscreen, fullscreen window). Cycling window mode skips fullscreen mode if its not a valid mode.
You can also toggle a "feature" that "wobbles" the Marks and Objects (different sine wave side to side) but this only works for unbaked Marks and Objects.



I have a dilemma/question.
I can't decide on whether Faux Car should have a pixelated display or not:


Click images for full-sized versions.
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1491
    • View Profile
    • Tank's Blog
    • Email
Re: Faux Car
« Reply #39 on: January 31, 2017, 12:33:42 pm »
Quote
I have a dilemma/question.
I can't decide on whether Faux Car should have a pixelated display or not:
Roll a dice. :)
SFGUI: Simple and Fast GUI library for SFML
Game Development Design articles
IRC: #sfml @ irc.boxbox.org

bitano

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
Re: Faux Car
« Reply #40 on: January 31, 2017, 03:34:59 pm »
Quote
I have a dilemma/question.
I can't decide on whether Faux Car should have a pixelated display or not:
Roll a dice. :)

Or a user setting !!! (it felt like multiple exclamation marks were required for extra emphasis)

Hapax

  • Hero Member
  • *****
  • Posts: 2789
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Faux Car
« Reply #41 on: January 31, 2017, 05:37:12 pm »
The pixelation is currently togglable.

One problem, though, is that I need a render texture to pixelate but can't use anti-alias on the render texture. This would mean that to use anti-alias, I would have to provide a work around that skips the render texture and draws directly onto the screen :(

Another problem, too, is that the "quality of the pixels" would determine the level of detail required in the actual textures. If pixelated, lesser textures are needed. If not pixelated, more detail can be added.

See? A dilemma! ;D
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 9355
    • View Profile
    • development blog
    • Email
Re: Faux Car
« Reply #42 on: February 15, 2017, 11:00:23 pm »
Just found this randomly on a Discord server and it reminded me of Faux Car. Maybe you can draw some "inspiration" from it. ;D

http://www.youtube.com/watch?v=3hPIf7ui1Do
Official FAQ: https://www.sfml-dev.org/faq.php
Nightly Builds: https://www.nightlybuilds.ch/
——————————————————————
Dev Blog: https://dev.my-gate.net/
Thor: http://www.bromeon.ch/libraries/thor/

mpeg3

  • Newbie
  • *
  • Posts: 13
  • gdinit@github
    • View Profile
Re: Faux Car
« Reply #43 on: February 15, 2017, 11:20:31 pm »
The pixelation is currently togglable.

One problem, though, is that I need a render texture to pixelate but can't use anti-alias on the render texture. This would mean that to use anti-alias, I would have to provide a work around that skips the render texture and draws directly onto the screen :(

Another problem, too, is that the "quality of the pixels" would determine the level of detail required in the actual textures. If pixelated, lesser textures are needed. If not pixelated, more detail can be added.

See? A dilemma! ;D
It's looking great. Well done. BTW I vote for non-pixelated version!

Hapax

  • Hero Member
  • *****
  • Posts: 2789
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: Faux Car
« Reply #44 on: February 16, 2017, 01:13:14 pm »
It's looking great. Well done. BTW I vote for non-pixelated version!
Thank you. I think it's going to have to have the option; might take a bit longer now though ;D

Just found this randomly on a Discord server and it reminded me of Faux Car. Maybe you can draw some "inspiration" from it. ;D
Haha. It's a bit further ahead than mine :(
Four things I don't like about it:
  • the constant drifting (why are all these games doing this now?),
  • the music,
  • the excessive and irritating post effects, and
  • the poor deer abuse!
;D

I've actually been working on this a bit recently. Finally got back to the stage where it has a drivable car :)
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

 

anything