0% found this document useful (0 votes)
10 views7 pages

Simple Game Engine

Uploaded by

Tarciso Carvalho
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views7 pages

Simple Game Engine

Uploaded by

Tarciso Carvalho
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

% The Simple Game Engine is a class from object-oriented programming.

% If you are unfamiliar with object oriented programming, here is a


quick
% crash course:
%
% Classes are a higher level of organizing programs beyond functions,
they
% group together the functions (called methods) and variables
(properties)
% of whatever it is you are trying to do. When you make a variable
(called
% an object) from a class, it has all the properties from that class
% bundled together. This mimics how we naturally categorize things in
real
% life. For example, cats are a class of animals, methods are the
things a
% cat can do (e.g. pounce, meow, etc), properties describe a cat (e.g.
% color, age, location, etc), and objects are individual cats (where
each
% of the properties has a set value).
%
% The one extra bit of syntax you need to understand what's going on
below
% is how to access properties of an object:
% Property "prop" of object "obj" is "obj.prop"

% The simpleGameEngine class inherets from the handle class because we


% want the game objects to be updated by their methods, specifically
% my_figure and my_image
classdef simpleGameEngine < handle
properties
sprites = {}; % color data of the sprites
sprites_transparency = {}; % transparency data of the sprites
sprite_width = 0;
sprite_height = 0;
background_color = [0, 0, 0];
zoom = 1;
my_figure; % figure identifier
my_image; % image data
end

methods
function obj = simpleGameEngine(sprites_fname, sprite_height,
sprite_width, zoom, background_color)
% simpleGameEngine
% Input:
% 1. File name of sprite sheet as a character array
% 2. Height of the sprites in pixels
% 3. Width of the sprites in pixels
% 4. (Optional) Zoom factor to multiply image by in final
figure (Default: 1)

1
% 5. (Optional) Background color in RGB format as a 3
element vector (Default: [0,0,0] i.e. black)
% Output: an SGE scene variable
% Note: In RGB format, colors are specified as a mixture
of red, green, and blue on a scale of 0 to 255. [0,0,0] is black,
[255,255,255] is white, [255,0,0] is red, etc.
% Example:
% my_scene =
simpleGameEngine('tictactoe.png',16,16,5,[0,150,0]);

% load the input data into the object


obj.sprite_width = sprite_width;
obj.sprite_height = sprite_height;
if nargin > 4
obj.background_color = background_color;
end
if nargin > 3
obj.zoom = zoom;
end

% read the sprites image data and transparency


[sprites_image, ~, transparency] = imread(sprites_fname);

% determine how many sprites there are based on the sprite


size
% and image size
sprites_size = size(sprites_image);
sprite_row_max = (sprites_size(1)+1)/(sprite_height+1);
sprite_col_max = (sprites_size(2)+1)/(sprite_width+1);

% Make a transparency layer if there is none (this happens


when
% there are no transparent pixels in the file).
if isempty(transparency)
transparency = 255*ones(sprites_size,'uint8');
else
% If there is a transparency layer, use repmat() to
% replicate is to all three color channels
transparency = repmat(transparency,1,1,3);
end

% loop over the image and load the individual sprite data
into
% the object
for r=1:sprite_row_max
for c=1:sprite_col_max
r_min = sprite_height*(r-1)+r;
r_max = sprite_height*r+r-1;
c_min = sprite_width*(c-1)+c;
c_max = sprite_width*c+c-1;
obj.sprites{end+1} =
sprites_image(r_min:r_max,c_min:c_max,:);
obj.sprites_transparency{end+1} =
transparency(r_min:r_max,c_min:c_max,:);

2
end
end
end

function drawScene(obj, background_sprites,


foreground_sprites)
% draw_scene
% Input:
% 1. an SGE scene, which gains focus
% 2. A matrix of sprite IDs, the arrangement of the
sprites in the figure will be the same as in this matrix
% 3. (Optional) A second matrix of sprite IDs of the same
size as the first. These sprites will be layered on top of the first
set.
% Output: None
% Example: The following will create a figure with 3 rows
and 3 columns of sprites
% drawScene(my_scene, [4,5,6;7,8,9;10,11,12],
[1,1,1;1,2,1;1,1,1]);

scene_size = size(background_sprites);

% Error checking: make sure the bg and fg are the same


size
if nargin > 2
if ~isequal(scene_size, size(foreground_sprites))
error('Background and foreground matrices of scene
must be the same size.')
end
end

num_rows = scene_size(1);
num_cols = scene_size(2);

% initialize the scene_data array to the correct size and


type
scene_data = zeros(obj.sprite_height*num_rows,
obj.sprite_width*num_cols, 3, 'uint8');

% loop over the rows and colums of the tiles in the scene
to
% draw the sprites in the correct locations
for tile_row=1:num_rows
for tile_col=1:num_cols

% Save the id of the current sprite(s) to make


things
% easier to read later
bg_sprite_id =
background_sprites(tile_row,tile_col);
if nargin > 2
fg_sprite_id =
foreground_sprites(tile_row,tile_col);
end

3
% Build the tile layer by layer, starting with the
% background color
tile_data =
zeros(obj.sprite_height,obj.sprite_width,3,'uint8');
for rgb_idx = 1:3
tile_data(:,:,rgb_idx) =
obj.background_color(rgb_idx);
end

% Layer on the first sprite. Note that the


tranparency
% data also ranges from 0 (transparent) to 255
% (visible)
tile_data = obj.sprites{bg_sprite_id} .*
(obj.sprites_transparency{bg_sprite_id}/255) + ...
tile_data .* ((255-
obj.sprites_transparency{bg_sprite_id})/255);

% If needed, layer on the second sprite


if nargin > 2
tile_data = obj.sprites{fg_sprite_id} .*
(obj.sprites_transparency{fg_sprite_id}/255) + ...
tile_data .* ((255-
obj.sprites_transparency{fg_sprite_id})/255);
end

% Calculate the pixel location of the top-left


corner
% of the tile
rmin = obj.sprite_height*(tile_row-1);
cmin = obj.sprite_width*(tile_col-1);

% Write the tile to the scene_data array


scene_data(rmin+1:rmin+obj.sprite_height,cmin
+1:cmin+obj.sprite_width,:)=tile_data;
end
end

% handle zooming
big_scene_data = imresize(scene_data,obj.zoom,'nearest');

% This part is a bit tricky, but avoids some latency, the


idea
% is that we only want to completely create a new figure
if we
% absolutely have to: the first time the figure is
created,
% when the old figure has been closed, or if the scene is
% resized. Otherwise, we just update the image data in the
% current image, which is much faster.
if isempty(obj.my_figure) || ~isvalid(obj.my_figure)
% inititalize figure
obj.my_figure = figure();

4
% set guidata to the key press and release functions,
% this allows keeping track of what key has been
pressed
obj.my_figure.KeyPressFcn =
@(src,event)guidata(src,event.Key);
obj.my_figure.KeyReleaseFcn =
@(src,event)guidata(src,0);

% actually display the image to the figure


obj.my_image =
imshow(big_scene_data,'InitialMagnification', 100);

elseif isempty(obj.my_image) ||
~isprop(obj.my_image, 'CData') || ~isequal(size(big_scene_data),
size(obj.my_image.CData))
% Re-display the image if its size changed
figure(obj.my_figure);
obj.my_image =
imshow(big_scene_data,'InitialMagnification', 100);
else
% otherwise just update the image data
obj.my_image.CData = big_scene_data;
end
end

function key = getKeyboardInput(obj)


% getKeyboardInput
% Input: an SGE scene, which gains focus
% Output: next key pressed while scene has focus
% Note: the operation of the program pauses while it waits
for input
% Example:
% k = getKeyboardInput(my_scene);

% Bring this scene to focus


figure(obj.my_figure);

% Pause the program until the user hits a key on the


keyboard,
% then return the key pressed. The loop is required so
that
% we don't exit on a mouse click instead.
keydown = 0;
while ~keydown
keydown = waitforbuttonpress;
end
key = get(obj.my_figure,'CurrentKey');
end

function [row,col,button] = getMouseInput(obj)


% getMouseInput
% Input: an SGE scene, which gains focus

5
% Output:
% 1. The row of the tile clicked by the user
% 2. The column of the tile clicked by the user
% 3. (Optional) the button of the mouse used to click
(1,2, or 3 for left, middle, and right, respectively)
%
% Notes: A set of “crosshairs” appear in the scene’s
figure,
% and the program will pause until the user clicks on the
% figure. It is possible to click outside the area of the
% scene, in which case, the closest row and/or column is
% returned.
%
% Example:
% [row,col,button] = getMouseInput (my_scene);

% Bring this scene to focus


figure(obj.my_figure);

% Get the user mouse input


[X,Y,button] = ginput(1);

% Convert this into the tile row/column


row = ceil(Y/obj.sprite_height/obj.zoom);
col = ceil(X/obj.sprite_width/obj.zoom);

% Calculate the maximum possible row and column from the


% dimensions of the current scene
sceneSize = size(obj.my_image.CData);
max_row = sceneSize(1)/obj.sprite_height/obj.zoom;
max_col = sceneSize(2)/obj.sprite_width/obj.zoom;

% If the user clicked outside the scene, return instead


the
% closest row and/or column
if row < 1
row = 1;
elseif row > max_row
row = max_row;
end
if col < 1
col = 1;
elseif col > max_col
col = max_col;
end
end
end
end

Not enough input arguments.

Error in simpleGameEngine (line 49)


obj.sprite_width = sprite_width;

6
Published with MATLAB® R2020b

You might also like