Sidebar Menu

Projects

  • Dashboard
  • Research Project
  • Milestones
  • Repository
  • Tasks
  • Time Tracking
  • Designs
  • Forum
  • Users
  • Activities

Login

  • Login
  • Webmail
  • Admin
  • Downloads
  • Research

Twitter

Tweets by stumathews
Stuart Mathews
  • Home
  • Blog
  • Code
  • Running
  • Gaming
  • Research
  • About
    • Portfolio
    • Info

Animated aliens and alternatives algorithms

Details
Category: Game Development
By Stuart Mathews
Stuart Mathews
18.Jul
Parent Category: Code
17 July 2019
Last Updated: 24 August 2019
Hits: 6417
  • Programming
  • Running
  • Game development
  • C++
  • XML
  • Asp.Net Core

Since Rules then Since then and Tuesdays, scribbling and haphazard interaction -  I managed after what felt like weeks of distraction, to finally piece together a 2D an animated sprite which faithfully iterates through 11 sequential keyframes within the same picture.

This is an example of what my green alien sprite sheet looks like. Later on I'll show you what it looks like animated.

A lot of the planning around this piece of work was around the algorithm.

In the end, the original algorithm I used to pan the view-port across the sprite sheet started fairly complex but gradually turned into a more simple one which, instead of trying to calculate the dimensions of the next frame based on a uniformly fixed key-frame size on the sprite-sheet, I instead decided to just hard-coded the 11 key-frame rectangle co-ordinates straight in as a simple array to demonstrate that animation is possible. 

The following series of C++ of code shows the process of changing the frame being drawn (update), within a frame lifetime threshold period, and selecting the appropriate frame dimensions (as a rectangle) encoded in an array to set the frame correctly (setFrameRect):

void Sprite::update()
{
	unsigned long timeSincelastFrame = timeGetTime() - m_TimeLastFrame;
	if(timeSincelastFrame >= m_Speed) {
		m_CurrentFrame++;
		if(m_CurrentFrame >= m_TotalFrames) 
			m_CurrentFrame = m_StartFrame;

		setFrameRect(m_CurrentFrame);
		m_TimeLastFrame = timeGetTime();	
	}
}

As mentioned above, that bit just determines when I should be switching to the next frame based on how long the old frame has been showing for.

Any longer than a threshold(m_Speed) and its time to move the animation on to the next frame. This is all kicked off by playing() the animation on the game object:

void Sprite::play()
{
	auto resource = GetResource();
	auto TmpSurface = resource->m_Surface;
	m_CurrentFrame = m_StartFrame;
	setFrameRect(m_CurrentFrame);
	m_TimeLastFrame = timeGetTime();
}

void Sprite::stop()
{
	stopped = true;
}

And then my little hack comes in next to set the desired view port on the resource i.e the sprite sheet shown previously:

void Sprite::setFrameRect(uint FrameNumber)
{	
	SDL_Rect typicalFrame[] = { 
		{0,0,66,92},
		{66,0,66,93},
		{132,0,66,93},
		{0,93,66,93},
		{66,93,66,93},
		{132,93,71,92},
		{0,186,71,93},
		{71,186,71,93},
		{142,186,70,92},
		{0,279,71,93},
		{71,279,66,97},
	};

	GetResource()->m_viewPort.x = typicalFrame[FrameNumber].x;
	GetResource()->m_viewPort.y = typicalFrame[FrameNumber].y;
	GetResource()->m_viewPort.w = typicalFrame[FrameNumber].w;
	GetResource()->m_viewPort.h = typicalFrame[FrameNumber].h;
}

It's not great because its hard-coded but it makes the concept work, which is the whole point of this exercise. It seems like it took me ages to do this, but there are a lot of other things I find competes for my time. Anyway, the full source code is here, its under the simplification branch which, is me trying to make my code as readable as possible (refactoring is one of the joys of programming in my opinion and calms me like zen).

The issue, that prompted this (hard coding) was that I had found some sprite-sheets online, which as it turns out were not uniform - each series in the animation was located in slightly different offset positions, so my original algorithm was no longer useful. The downloaded sprite-sheets do all have a mixture of XML and JSON associated key-frame coordinates code into meta files, which I realise now is because the sprite-sheets are not uniform... 

So moving forward, I think what I’ll do, is cater for this by implementing both a JSON and a XML loader that can read in the associated coordinates from the meta files for the sprite-sheet and dynamically using them to determine the frame coordinates. For now though, I’m going to focus on other aspects of my engine...

Here is the basic idea, which also shows some scene management and resource management i.e swapping resources in/out of memory on scene/level changes and you'll notice that my last scene has a cute animated green little alien - air walking. 

 

Though while it is very basic and not very exciting, it's very interesting from a programming perspective, particularly the management of resources and key-frame animation.

I’ve got to work on the event management system which currently holds a list of events that other parts of the engine send to it (like the keyboard events, the scene change events and the logic processing events), however I’ve stored them in a vector of shared pointers to event objects which I never remove even after I’ve processed them - so I need to fix that among other things.

Apart from all of this, and changing track a bit now - I went for a 10 km run home the other day after my train broke down partway to work. I posted my fastest 10 km which at a pace of 4’28/km and a training effect of 3.9 was quite pleasing.

We broke down at round just past Ickenham station and all had to get up and shuffle in a straight line off the train, through the driver's compartment, which was on the other side of the train. I never quite figured out what happened but we were told to walk to the next station which was West Ruislip which was about 30 mins away. It was nice however to see it again as it was a frequent part of my previous running-to-work journeys.

This is the route I ran:

 

So that was good(I like running).

I have found a mother duck and her two ducklings about outside recently, just below my balcony, and every day at around 6:30 she leaves her ducklings and they go bonkers, tweeting and wandering around aimlessly around the courtyard, searching for her. She inevitably comes back at some point as I see them the next day. They start tweeting at about 6:30am which is useful as that's when I should be getting up. 

In other more alternative news, I had my first food shop in Lidl this evening, and it was quite interesting. I decided I’d try it out because they’ve opened up within the local shopping centre and I’d walked past it a few times going to the Cinema on weekends. Though, it always seemed really busy and I didn’t really want to be faffing about in the frozen-veg aisle while its busy and I'm on a weekend break. But today, after coming home and getting out of the station, I thought I’d do an “alternative shop”. So instead of turning right towards Tesco, I did 270 to Lidl. Interesting experiance...

They have this pretty whacky middle aisle setup which is amongst all the food shelves and has everything from kayaks and school wear to Tupperware and solar-panelled garden lamps. This is really strange as you're browsing for cereal, coffee, cheese or whatever and straight out of nowhere, boom you're faced with beach-balls or mini-outdoor trampolines.  Everything was pretty well priced.

I didn’t get much but I did circle the shop-floor about 4 times and each time I found something else that was interesting. It probably  helped that the shopping-baskets were on wheels and although not great at cornering, are really fun to use! I always carry my metal shopping basket around, the idea of racing my food around the aisles was cool. Note to self, I must grow up.

I bought a new book on Game AI programming which I started reading on the way home the other day which was quite interesting, though it was a bit specific and having not spent a lot of time understanding utility theory and/or implementations thereof or to a great extend, finite-state machines to simulate intelligence - it was a slow read.

I did find the introductory interesting about how AI not so much trying to simulate absolute intelligence, because if you did that, games really wouldn’t be fun – they’d be accurate but actually seem a little out of place. The brain is more forgiving about large discrepancies in intelligence and actually enjoys it when its within the context of suspending one-belief, so sometimes the time and effort to be 100% accurate is not particularly well spent. The book is a bit big so I’m going to leave it at home. I'll add it to my chain on books that I jump around.

I’m currently in the process of investigating Kali Linux as I’m going to use it to understand more about analysing file systems.

I installed it on a virtual machine on my laptop this morning on the way to work on the train. I had to carry my laptop out of the train half-open because it's still hasn’t installed grub boot loader by the time the train pulled into Liverpool Street station. I’d spend most of the weekend studying about how aspects of the Window OS can be interrogated to determine a timeline of events which might otherwise constitute criminal activity – things like how the hibernate file works, what gets put into it, what is installed in various parts of the registry etc.

I’ve got some practical things to do around undeleting some files and ‘carving’ out deleted files from ‘unallocated’ clusters so I’m basically prepping for this. 

I also spent some time recently working on a tricky computer problem. Specifically, it was to do with package references and dependencies in a .Net project, which really sent me around the houses. I spend nearly an entire day 'playing with it' and after figuring it out, reminded me of a paper I recently read. And this is going to sound boring but bear with it:

The paper was about how people learn, and specifically about how experience ie doing something facilitates deeper understanding and how tacit information is unlocked whilst in the act of doing it - what has previously been called "dynamic affordance". This might sound pretty boring and even pretty obvious: that doing is an important component of experience however its more than that - it talked about how really the key to the experience, is bringing in multi-faceted approaches coupled with this doing process - 'playing' and 'trying' is one thing, but doing it with a certain state of mind, having an inquisitive intent is hugely important. Coupled that with actually enjoying the act of problem finding makes any experience gained almost next-level.

It was a long annoying problem and sometimes, that noise I'm hearing from the computer sounds not like the hard drive turning but my computer chuckling at me - but that's ok - as long as its having a good time.

I've also been reading a book about small and helpful mathematics concepts that are explained beautifully which inspired me to write about Rules then Since then.

For example, recently I've been reading about statistics, specifically about standard deviation and variances from it are important in assessing the 'normality' of result sets.

I also dabbled in considering tiny magnitudes such as femtometers that can be used to measure things like the space between two atoms and/or neutrinos and others for massive things like the size of the universe through AU's or astronomical units - which is the distance from the centre of the earth to the sun. Pretty interesting stuff.

I'm also learning about other aspects of arithmetic and in particular calculating the returns on portfolios which I'm really just getting to the beginning of. For example, recently I've been seeing how a return on an investment can be decomposed into the time and money invested in that investment, which then can indicate how that investment really performed. Still early days.

There is a lot of interesting stuff out there to learn.

Retro sounds, Event Manager and some running

Details
Category: Game Development
By Stuart Mathews
Stuart Mathews
05.May
Parent Category: Code
05 May 2019
Last Updated: 05 May 2019
Hits: 4682
  • Programming
  • Game development
  • C++

Since Basic key frame animations, implicit casts and some other aspect, I've continued to make gradual improvements to my game prototype which now includes an event manager and some cool retro sounds.

The event manager concept is simple, when we get a game event from the keyboard, we send the event to the event manager and it forwards a copy of that event to each subscriber of that event. What I did was have my actors subscribe to a particular event during initialization and then use the event manager to decouple these actors from the keyboard handling logic. In fact, this allows any object to do things based on events without knowing where the events came from. 

The concept is routinely used in event-based programming that I've used before in C# and Java particularly around GUI design and having read about it in GCC4 a while back, I thought I'd have a stab at implementing it. As you might recall this was part of the architecture detailed in A simple game engine architecture. 

The basis of the event system as described above is simple:

#pragma once
#include <vector>
#include <memory>
#include "Event.h"
#include "EventSubscriber.h"
class EventManager
{
public:
	EventManager();
	void RegisterEvent(std::shared_ptr<Event> evt);
	void SubscribeToEvent(EventType type, EventSubscriber* you);
	~EventManager();
	void ProcessEvents();
private:	
	std::vector<std::shared_ptr<Event>> events;
	std::map<EventType, std::vector<EventSubscriber*>> event_subscribers;

};

The system maintains a list of events and who is subscribed to them. When its asked to process the events as part of the update() phase of the game loop, it marries up subscribers with events. Simple:

#include "EventManager.h"
#include <vector>
#include "EventSubscriber.h"
#include <iostream>


EventManager::EventManager()
{
}

void EventManager::RegisterEvent(std::shared_ptr<Event> evt)
{
	std::cout << "Registering event." << std::endl;
	events.push_back(evt);
}

void EventManager::SubscribeToEvent(EventType type, EventSubscriber* you)
{
	std::cout << "Subscribed to event" << std::endl;
	event_subscribers[type].push_back(you);	
}

EventManager::~EventManager(){}

void EventManager::ProcessEvents()
{
	// go through all the events and call all ther subscribers telling them about the event
	if(events.size() != 0)
	{
		std::cout << "Processing events..." << std::endl;
	}
	for(std::vector<std::shared_ptr<Event>>::iterator it = events.begin(); it != events.end();it++)
	{
		std::shared_ptr<Event> evt = *it;
		std::vector<EventSubscriber*> subscribers  = event_subscribers[evt->m_eventType];
		for(EventSubscriber* subscriber : subscribers)
		{
			subscriber->ProcessEvent(evt);			
		}		
	}
	events.clear();
}

It works quite well and though I haven't tried it for more than one type of event (I've just designed a PositionChangedEvent type), it looks promising. I'm not too worried about performance at this point. I've implemented a concept of an event subscriber which details how objects that would like to subscribe to events should structure themselves so that the event manager can contact them with the events that they subscribed to.

This means basically that my actors are Event Subscribers, capable of processing events passed to them by the event manager. This is how my Ball class deals with the PositionChangedEvent:

#include "Ball.h"
#include "Events.h"
#include <memory>
#include "Event.h"
#include <iostream>

void Ball::ProcessEvent(std::shared_ptr<Event> evt)
{
	// Handle PositionChangeEvents
	if(evt->m_eventType == PositionChangeEventType)
	{
		std::shared_ptr<PositionChangeEvent> cpe = std::dynamic_pointer_cast<PositionChangeEvent>(evt);
		if(cpe->m_direction == Up){			
			MoveUp();
			std::cout << "Move up event processed" << std::endl;
		}
		if(cpe->m_direction == Down){
			MoveDown();
			std::cout << "Move down event processed" << std::endl;
		}
		if(cpe->m_direction == Left){
			MoveLeft();
			std::cout << "Move left event processed" << std::endl;
		}
		if(cpe->m_direction == Right){
			MoveRight();
			std::cout << "Move right event processed" << std::endl;
		}
	}
}

Ball::~Ball()
{
	
}

This is hardly a complete solution but more a work in progress, a game prototype if you will.

If you want you can have a look at how I've defined my events, which is also quite rudimentary.

In other news, I attended my course on C programming recently and it was like my Event Manager, a little rudimentary however that doesn't mean it wasn't useful: I know exactly where I need to be, come Oct time.

Started learning about Digital Forensics which I've found it quite interesting, and my last couple of runs in Four close run-ins have been really good and I've enjoyed them tremendously. I read a paper about Digital triage today. It is here if you want to read it:

 

The sum of today’s activity so far(I need to get to bed earlier): A survey of digital forensic investigator decision processes and measurement of decisions based on enhanced preview - ScienceDirect https://t.co/dHT3gQEjNT

— Stuart Mathews (@stumathews) May 5, 2019

 

Basic key frame animations, implicit casts and some other aspect

Details
Category: Game Development
By Stuart Mathews
Stuart Mathews
01.May
Parent Category: Code
01 May 2019
Last Updated: 05 May 2019
Hits: 5500
  • Game development
  • C++
  • Math
  • C#
  • Aspect Oriented Programming

Since Gaming and Easter, Heroku, Postmodernism, DataFlow, Math and Software Engineering, I got a lot done today with regards to developing my simple game (which doesn't really even have a purpose yet but it just needs to be something) and even though I coded for only a bit - some days just thinking about coding while you're not coding fuels the coding session when you do get around to it. I find that this happens a lot especially in the shower.

Anyway, most of the work was done on the train this morning to work and then back from my C programming class.

  • Left-hand rule visualized today beautifully using 3D math primer for graphics and game development (2012, Fletcher et al)
  • Great use-case for implicit casts in C# at work today
  • Used actor objects in the game based on the advice in GCC4
  • Use static member in C++ class to represent the SDL Draw functionality in its own dedicated class Drawing::DrawRectangle()
  • Used inheritance to make a Ball class from an Actor base class which was the right thing to do
  • Used virtual to allow my ball and paddle (I think I'm going for a version of Pong here) to implement their own drawing and logic code (look ma no hands!)
    • Needed to use pure virtual members and thus abstract class to do this.
  • Got a chance to use the new auto and for constructs in c++ 14 to iterate over my vector of game objects ie actors
  • Used Vector to house my game objects in my GameWorldData struct
  • Implemented draw() and doLogic() in actors so that they can draw themselves - I mentioned this already
  • Used member initialization in the constructor - this was to ensure that my Positions were initialized correctly
  • Used protected members in c++ especially in the Actor class so that my Ball class could access the PosX and PosY members.
  • Stored pointer to base class in vector thereby making inroads to the next point - polymorphism 
  • Used polymorphism to call draw() and doLogic() on actor base class instances stored in vector

So a good days work really.

At work, I put together a Post Sharp aspect that transform a methods parameters, specifically that of a specific type but I found that while it worked great, it was a bit magic and you can’t really understand easily why, if you’re reading the code for the first time, what was going on. So I decided that even though putting attributes on methods like that was cool, it was a bit too decoupled (yes that’s possible! So decoupled you can’t see why it applies!). I instead moved to simply transform incoming parameters by enforcing that they can be implicitly transformed by  a new type with an implicit cast built in, so strings coming in would be turned into these new objects automatically (I changed the type from string to this new Type) and these new objects transform the string on-demand by way of automatic implicit casting them Pretty cool. This is what it looks like:

using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Common
{
    /// <summary>
    /// A string that will automatically be represented as a valid code if 
    /// it is created with and invalid string, otherwise the orignal string is used
    /// </summary>
    public class AutoCode
    {
        /// <summary>
        /// The sanitized, generated code or the original 
        /// PW code if it wasn't invalid
        /// </summary>
        public string Value { get;set; }

        /// <summary>
        /// Indication if this code had to generate a 
        /// compatible code from the provided PW code
        /// </summary>
        public bool WasCodeOriginallyInvalid { get; }

        /// <summary>
        /// We can track the original invalid code if it was 
        /// invalid, see <see cref="WasCodeOriginallyInvalid"/>
        /// </summary>
        public string OriginalInvalidValue { get; }

        /// <summary>
        /// Converts the provided code into a 
        /// compatible code if its invalid to begin with
        /// </summary>
        /// <remarks>An invalid code is a non-alphanumeric code</remarks>
        /// <param name="value"></param>
        public AutoCode(string value)
        {
            // Turn the invalid portfolio code into a valid 
            // code which is a Hash of the invalid code such that
            // we can use the invalid code again to determine the same 
            // auto generated hash code
            // This hash is only substituted for the code if the 
            // incoming PW code is non alphanumeric which is invalid as far as 
            // using that as a code too
            const string alphanumericRegex = @"^[a-zA-Z0-9-]*$"; // note we're
            // ok with '-' so added this into pattern
            if(!Regex.IsMatch(value, alphanumericRegex))
            {
                WasCodeOriginallyInvalid = true;
                OriginalInvalidValue = value;
                using (var sha256 = new SHA256Managed())
                {
                    // This might be slow but its accurate and we'll 
                    // cross that bridge when we get there ("Make it work,
                    // then make it work fast" - Dennis Richie )
                    // An alternative might be djb2 as described here: 
                    // http://www.cse.yorku.ca/~oz/hash.html
                    var raw = Encoding.Default.GetBytes(value);

                    // PWCode -> SHA235(PWCode). 
                    // Note that by default a sha256 hash is delimited
                    // by an invalid '-' character, remove it
                    Value = BitConverter.ToString(sha256.ComputeHash(raw))
                            .Replace("-", string.Empty);;
                }
                
            }
            else
            {
                Value = value;
                WasCodeOriginallyInvalid = false;
                OriginalInvalidValue = string.Empty;
            }
        }

        /// <summary>
        /// You can use a AutoCode anywhere you can use a string because it
        /// will be converted to it implicitly
        /// </summary>
        /// <param name="code"></param>
        public static implicit operator string(AutoCode code)
        {
            return code.Value;
        }

        /// <summary>
        /// You can use a string anywhere you can use a AutoCode -
        /// because it will be converted to one implicitly
        /// </summary>
        /// <param name="code"></param>
        public static implicit operator AutoCode(string code)
        {
            return new AutoCode(code);
        }

        /// <summary>
        /// You can see the sanitized value directly
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            // You can get the sanitized value of a Code
            return Value;
        }
    }
}

But then I just threw it away.

So that basically means that I changed functions from using String to this new Type called AutoCode() and when you pass any string into a function that needs a AutoCode it won't complain, it'll just suck it into that new AutoCode type. Pretty neat and its easier to reason about that using the Aspect Orientated approach I mentioned previously.

But for interest's sake this is the Aspect I created:

 /// <inheritdoc />
    /// <summary>
    /// Automatically turn Portfolio.Code to Sanitized version of Portfolio.Code
    /// </summary>
    [Serializable]
    public class SanitizePWPortfolioCodeAttribute : MethodInterceptionAspect
    {
        public override void OnInvoke(MethodInterceptionArgs args)
        {
            // Determine which parameter is the PW Portfolio object
            var param = args.Method.GetParameters()
                         .SingleOrDefault(p => p.ParameterType == 
                         typeof(Services.PortfolioServices.Portfolio));
            if(param != null)
            {
                // Get it
                var portfolioArg = (Portfolio)args.Arguments[param.Position];
                
                if(portfolioArg == null)
                {
                    args.Proceed();
                    return;
                }
                // Modify it if needed
                // Note that a AutoCode will turn into a valid 
                // code automatically (implicit conversion to string)
                portfolioArg.Code =  new AutoCode(portfolioArg.Code);

                // Pass it back in to the pipeline
                args.Arguments.SetArgument(param.Position, portfolioArg);
                
            }
            args.Proceed();
        }
    }

Oh and checkout my new Balls that draw themselves are here ...

Out.

 

More Articles …

  1. Gaming
  2. Measuring the duration of a function in C++
  3. A simple game engine architecture
  4. Direct X theory and principles
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Page 5 of 9

Blog RSS Feed