├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md └── platformerGame ├── AABB.cs ├── App ├── GameScene.cs ├── GameState.cs ├── MainMenu.cs └── SfmlApp.cs ├── AssetLoader.cs ├── Camera.cs ├── Containers ├── GridOccupant.cs ├── IPool.cs ├── cQuadTree.cs ├── cSpatialCell.cs └── cSpatialGrid.cs ├── DrawingBase.cs ├── Effects └── EffectSystem.cs ├── GameObjects ├── Bird.cs ├── EntityGrid.cs ├── GameObjectGrid.cs ├── PickupInfo │ └── cPickupInfo.cs ├── cBullet.cs ├── cCharacter.cs ├── cGameObject.cs ├── cMonster.cs ├── cPickupAble.cs ├── cPlayer.cs └── cTurret.cs ├── GlobalClock.cs ├── IDrawable.cs ├── IGame.cs ├── Inventory ├── Weapons │ ├── cMachineGun.cs │ ├── cShotgun.cs │ └── cWeapon.cs ├── cInventory.cs └── cItem.cs ├── Map ├── cMapData.cs ├── cTile.cs ├── cTileLayer.cs └── cTileMapRenderer.cs ├── MapCollider.cs ├── Particles ├── EmissionInfo.cs ├── IParticleContainer.cs ├── Particle.cs ├── cBaseParticleController.cs ├── cExplosionController.cs ├── cFireworksController.cs ├── cParticleManager.cs ├── cParticlePool.cs ├── cParticlePoolList.cs └── cSprayController.cs ├── Program.cs ├── Regulator.cs ├── Rendering ├── RenderGroup.cs ├── cAnimatedSpriteRenderer.cs ├── cAnimationAssets.cs ├── cBaseRenderer.cs └── cSpriteRenderer.cs ├── SfmlApp.cs ├── ShakeScreen.cs ├── StateBase └── IState.cs ├── Utilities ├── AppMath.cs ├── AppRandom.cs ├── AppTimer.cs ├── Constants.cs ├── MyRect.cs ├── ProbabilityRoll.cs ├── Quaternion.cs ├── Utils.cs ├── cCollision.cs ├── cSatCollision.cs └── cTimeInfo.cs ├── cAnimation.cs ├── cEnvironment.cs ├── cLight.cs ├── cLightSystem.cs ├── cPlayerInfo.cs ├── cSpriteState.cs ├── cSpriteStateController.cs ├── cWaterBlock.cs ├── cWorld.cs ├── constants.json └── sfLine.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /platformerGame/bin 2 | /platformerGame/obj 3 | *.dll 4 | *.lib 5 | *.config 6 | *.sln 7 | *.csproj 8 | /.vs 9 | *VC.db 10 | *.opendb 11 | /platformerGame/UNUSED 12 | *.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | platformerGame 2 | ========= 3 | 4 | ## 2D sidescrolling platformer experimental project, built with C# and [SFML.NET](https://www.sfml-dev.org/download/sfml.net/). 5 | 6 | This project is under development. 7 | 8 | ### Contains so far: 9 | * Scrolling map, player centered in camera 10 | * Simple light system 11 | * Character, bullet and particle collision detection with the map, and bullet-monster collision with hit handler 12 | * Particle systems 13 | * Wavy water blocks 14 | * Simple graphics, animation and sprite state control 15 | * Levels made by Tiled, loaded from .tmx files 16 | * Tile layers added 17 | * Monsters can drop "pickup-able" things 18 | 19 | ![platformer_b](https://user-images.githubusercontent.com/23726291/41161580-a0b7f006-6b33-11e8-99d9-5c44881ced17.gif) 20 | 21 | All rights reserved. 22 | -------------------------------------------------------------------------------- /platformerGame/AABB.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.System; 7 | using SFML.Graphics; 8 | using platformerGame.Utilities; 9 | 10 | namespace platformerGame 11 | { 12 | class AABB 13 | { 14 | public Vector2f topLeft; 15 | public Vector2f rightBottom; 16 | public Vector2f center; 17 | public Vector2f dims; // full (not half) width and height 18 | public Vector2f halfDims; // half width and height 19 | 20 | 21 | public AABB() 22 | { 23 | topLeft = new Vector2f(); 24 | rightBottom = new Vector2f(); 25 | center = new Vector2f(); 26 | dims = new Vector2f(0, 0); 27 | halfDims = new Vector2f(0, 0); 28 | } 29 | 30 | public AABB(float left, float top, float width, float height) 31 | { 32 | topLeft = new Vector2f(left, top); 33 | dims = new Vector2f(width, height); 34 | halfDims = dims / 2.0f; 35 | rightBottom = new Vector2f(topLeft.X + dims.X, topLeft.Y + dims.Y); 36 | center = new Vector2f(topLeft.X + halfDims.X, topLeft.Y + halfDims.Y); 37 | } 38 | 39 | public AABB(FloatRect rect) : this(rect.Left, rect.Top, rect.Width, rect.Height) { } 40 | 41 | public AABB(Vector2f top_left, Vector2f dims) 42 | { 43 | topLeft = top_left; 44 | this.dims = dims; 45 | halfDims = dims / 2.0f; 46 | rightBottom = new Vector2f(topLeft.X + dims.X, topLeft.Y + dims.Y); 47 | center = new Vector2f(topLeft.X + halfDims.X, topLeft.Y + halfDims.Y); 48 | } 49 | 50 | public AABB(AABB other) 51 | { 52 | SetDims(other.dims); 53 | SetPosByTopLeft(other.topLeft); 54 | } 55 | 56 | public void SetDims(Vector2f dims) 57 | { 58 | this.dims = dims; 59 | halfDims.X = dims.X / 2.0f; 60 | halfDims.Y = dims.Y / 2.0f; 61 | } 62 | 63 | public void SetPosByRightBottom(Vector2f new_right_bottom) 64 | { 65 | this.rightBottom = new_right_bottom; 66 | 67 | this.topLeft.X = new_right_bottom.X - dims.X; 68 | this.topLeft.Y = new_right_bottom.Y - dims.Y; 69 | 70 | this.center.X = new_right_bottom.X - halfDims.X; 71 | this.center.Y = new_right_bottom.Y - halfDims.Y; 72 | } 73 | 74 | public void SetPosByTopLeft(Vector2f top_left) 75 | { 76 | topLeft.X = top_left.X; 77 | topLeft.Y = top_left.Y; 78 | 79 | rightBottom.X = topLeft.X + dims.X; 80 | rightBottom.Y = topLeft.Y + dims.Y; 81 | 82 | center.X = topLeft.X + halfDims.X; 83 | center.Y = topLeft.Y + halfDims.Y; 84 | } 85 | 86 | public void SetPosByCenter(Vector2f center) 87 | { 88 | this.center.X = center.X; 89 | this.center.Y = center.Y; 90 | 91 | topLeft.X = this.center.X - halfDims.X; 92 | topLeft.Y = this.center.Y - halfDims.Y; 93 | 94 | rightBottom.X = this.center.X + halfDims.X; 95 | rightBottom.Y = this.center.Y + halfDims.Y; 96 | } 97 | 98 | public void Scale(Vector2f factors, Vector2f relative_to) 99 | { 100 | Transform t = Transform.Identity; 101 | t.Scale(factors, relative_to); 102 | FloatRect result = t.TransformRect(this.AsSfmlFloatRect()); 103 | this.SetDims(new Vector2f(result.Width, result.Height)); 104 | this.SetPosByTopLeft( new Vector2f(result.Left, result.Top)); 105 | } 106 | 107 | public MyFloatRect AsMyFloatRect() 108 | { 109 | return new MyFloatRect(topLeft.X, topLeft.Y, dims.X, dims.Y); 110 | } 111 | 112 | public MyIntRect AsMyIntRect() 113 | { 114 | return new MyIntRect((int)topLeft.X, (int)topLeft.Y, (int)dims.X, (int)dims.Y); 115 | } 116 | 117 | public FloatRect AsSfmlFloatRect() 118 | { 119 | 120 | return new FloatRect(topLeft, dims); 121 | } 122 | 123 | public IntRect AsSfmlIntRect() 124 | { 125 | return new IntRect((int)topLeft.X, (int)topLeft.Y, (int)dims.X, (int)dims.Y); 126 | } 127 | 128 | public AABB ShallowCopy() 129 | { 130 | return (AABB)this.MemberwiseClone(); 131 | } 132 | 133 | public AABB DeepCopy() 134 | { 135 | return new AABB(this); 136 | } 137 | 138 | /// 139 | /// for fast SA. collision detection (see @cSatCollision.cs) 140 | /// 141 | /// 142 | public Vector2f[] getLocalVertices() 143 | { 144 | // return Utilities.cSatCollision.BuildBox(dims.X, dims.Y); 145 | 146 | Vector2f[] b = new Vector2f[4] 147 | { 148 | new Vector2f(-halfDims.X, -halfDims.Y), 149 | new Vector2f(halfDims.X, -halfDims.Y), 150 | new Vector2f(halfDims.X, halfDims.Y), 151 | new Vector2f(-halfDims.X, halfDims.Y) 152 | }; 153 | 154 | return b; 155 | 156 | } 157 | 158 | public Vector2f getTopRight() 159 | { 160 | return new Vector2f(topLeft.X + dims.X, topLeft.Y); 161 | } 162 | 163 | public Vector2f getLeftBottom() 164 | { 165 | return new Vector2f(topLeft.X, topLeft.Y + dims.Y); 166 | } 167 | 168 | public float diagonalLength() 169 | { 170 | return AppMath.getDiagonal(this.dims); 171 | } 172 | 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /platformerGame/App/GameState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.System; 7 | using SFML.Graphics; 8 | using SFML.Window; 9 | 10 | namespace platformerGame.App 11 | { 12 | /// 13 | /// A játék állapotát biztosító alaposztály. Ilyen állapot lehet pl. Főmenü, játék vagy új szint. 14 | /// 15 | abstract class GameState 16 | { 17 | protected SfmlApp appControllerRef = null; 18 | protected Camera camera = null; 19 | protected AssetContext resourceAssets = null; 20 | 21 | //protected View m_View; 22 | public GameState(SfmlApp app_ref) 23 | { 24 | appControllerRef = app_ref; 25 | resourceAssets = new AssetContext(); 26 | //m_View = new View(); 27 | } 28 | /// 29 | /// Az állapot induláskor kell végre hajtani 30 | /// 31 | public abstract void Enter(); 32 | 33 | public virtual void BeforeUpdate() { } 34 | public abstract void UpdateFixed(float step_time); 35 | public abstract void UpdateVariable(float step_time = 1.0f); 36 | 37 | public abstract void Render(RenderTarget destination, float alpha); 38 | 39 | // Events 40 | public abstract void HandleMouseButtonPressed (MouseButtonEventArgs e); 41 | public abstract void HandleMouseButtonReleased (MouseButtonEventArgs e); 42 | public abstract void HandleMouseMoved (MouseMoveEventArgs e); 43 | 44 | public abstract void HandleKeyPressed (KeyEventArgs e); 45 | public abstract void HandleKeyReleased (KeyEventArgs e); 46 | public abstract void HandleTextEntered (TextEventArgs e); 47 | 48 | /// 49 | /// Must be called when exiting from a state 50 | /// 51 | public abstract void Exit(); 52 | 53 | public Vector2f GetMousePosInWindow() 54 | { 55 | Vector2i m = Mouse.GetPosition(appControllerRef.MainWindow); 56 | Vector2f mf = appControllerRef.MainWindow.MapPixelToCoords(m); 57 | 58 | return mf; // new Vector2f(m.X, m.Y); 59 | } 60 | 61 | public Vector2f GetMousePos() 62 | { 63 | Vector2i iMp = Mouse.GetPosition(appControllerRef.MainWindow); 64 | 65 | Vector2f mousePos = appControllerRef.MainWindow.MapPixelToCoords(iMp, camera.View); 66 | 67 | return mousePos; 68 | } 69 | 70 | public SfmlApp AppController 71 | { 72 | get { return this.appControllerRef; } 73 | } 74 | 75 | public Camera Camera 76 | { 77 | get { return this.camera; } 78 | } 79 | 80 | public AssetContext Assets 81 | { 82 | get { return this.resourceAssets; } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /platformerGame/AssetLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | 8 | using SFML.Graphics; 9 | using SFML.Audio; 10 | using SFML.System; 11 | 12 | using platformerGame.Utilities; 13 | 14 | namespace platformerGame 15 | { 16 | class AssetContext 17 | { 18 | public string[] FontNames { get; private set; } 19 | public string[] TextureNames { get; private set; } 20 | public string[] SoundNames { get; private set; } 21 | 22 | public Dictionary Textures { get; private set; } 23 | public Dictionary Fonts { get; private set; } 24 | public Dictionary SoundBuffers { get; private set; } 25 | public List Sounds { get; private set; } 26 | 27 | public AssetContext() 28 | { 29 | Textures = new Dictionary(); 30 | Fonts = new Dictionary(); 31 | SoundBuffers = new Dictionary(); 32 | Sounds = new List(); 33 | } 34 | 35 | public void LoadResources(string[] font_names = null, string[] textures_names = null, string[] sound_names = null) 36 | { 37 | // return Task.Factory.StartNew(() => { }); 38 | this.ClearResources(); 39 | 40 | this.FontNames = font_names; 41 | this.TextureNames = textures_names; 42 | this.SoundNames = sound_names; 43 | 44 | //loading fonts 45 | if (this.FontNames != null) 46 | { 47 | foreach (string fontName in this.FontNames) 48 | { 49 | Tuple data = AssetLoader.LoadFont(fontName); 50 | this.TryAddFont(data); 51 | } 52 | } 53 | 54 | //loading textures 55 | if (this.TextureNames != null) 56 | { 57 | foreach (string texName in this.TextureNames) 58 | { 59 | Tuple data = AssetLoader.LoadTexture(texName); 60 | this.TryAddTexture(data); 61 | } 62 | } 63 | 64 | 65 | //loading sounds 66 | if (this.SoundNames != null) 67 | { 68 | foreach (string soundName in this.SoundNames) 69 | { 70 | Tuple data = AssetLoader.LoadSound(soundName); 71 | this.TryAddSound(data); 72 | } 73 | } 74 | } 75 | 76 | public void TryAddFont(Tuple font_data) 77 | { 78 | if (false == Fonts.ContainsKey(font_data.Item1)) 79 | { 80 | Fonts.Add(font_data.Item1, font_data.Item2); 81 | } 82 | } 83 | 84 | /* 85 | public string TryAddTexture(string path) 86 | { 87 | string id_name = AssetManager.GenerateIDFromFilePath(path); 88 | Texture t = AssetManager.LoadAndReturnTexture(path); 89 | this.TryAddTexture(new Tuple(id_name, t)); 90 | return id_name; 91 | } 92 | */ 93 | 94 | public void TryAddTexture(Tuple texture_data) 95 | { 96 | if (false == Textures.ContainsKey(texture_data.Item1)) 97 | { 98 | Textures.Add(texture_data.Item1, texture_data.Item2); 99 | } 100 | } 101 | 102 | public void TryAddSound(Tuple sound_data) 103 | { 104 | if (false == SoundBuffers.ContainsKey(sound_data.Item1)) 105 | { 106 | SoundBuffers.Add(sound_data.Item1, sound_data.Item2); 107 | } 108 | } 109 | 110 | public Font GetFont(string id) 111 | { 112 | Font f; 113 | if (Fonts.TryGetValue(id, out f)) 114 | { 115 | return f; 116 | } 117 | 118 | return null; 119 | } 120 | 121 | public Texture GetTexture(string id) 122 | { 123 | Texture t; 124 | if (Textures.TryGetValue(id, out t)) 125 | { 126 | return t; 127 | } 128 | 129 | return null; 130 | } 131 | 132 | public void PlaySound(string id, int volume = 50, Vector2f pos = default(Vector2f)) 133 | { 134 | Sound s = new Sound(SoundBuffers[id]); 135 | 136 | s.Volume = volume; 137 | s.RelativeToListener = true; 138 | s.Position = new Vector3f(pos.X, 0.0f, pos.Y); 139 | //s.MinDistance = 5.0f; 140 | //s.Attenuation = 10.0f; 141 | s.Play(); 142 | 143 | //sounds.Find(snd => snd.SoundBuffer == soundBuffers[id]); 144 | 145 | Sounds.Add(s); 146 | Sounds.RemoveAll(snd => snd.Status != SoundStatus.Playing); 147 | } 148 | 149 | public void ClearResources() 150 | { 151 | Textures.Clear(); 152 | Fonts.Clear(); 153 | SoundBuffers.Clear(); 154 | Sounds.Clear(); 155 | } 156 | 157 | public void Mix(AssetContext other_context) 158 | { 159 | 160 | } 161 | } 162 | 163 | class AssetLoader 164 | { 165 | public const string ROOT_PATH = "Resources/"; 166 | public const string TEX_RESOURCE_PATH = "textures/"; 167 | public const string TILESET_PATH = TEX_RESOURCE_PATH + "tilesets/"; 168 | public const string FONT_RESOURCE_PATH = "fonts/"; 169 | public const string SOUND_RESOURCE_PATH = "sounds/"; 170 | 171 | 172 | static AssetLoader() 173 | { 174 | } 175 | 176 | public static string GenerateIDFromFilePath(string file_path) 177 | { 178 | file_path = file_path.Replace('\\', '/'); 179 | int start = file_path.LastIndexOf('/')+1; 180 | int len = Math.Abs(file_path.LastIndexOf('.') - start); 181 | return file_path.Substring(start, len); 182 | } 183 | 184 | public static Tuple LoadFont(string file_name) 185 | { 186 | string path = Path.Combine(ROOT_PATH, FONT_RESOURCE_PATH, file_name); 187 | Font f = new Font(path); 188 | 189 | string id_name = GenerateIDFromFilePath(file_name); 190 | 191 | return new Tuple(id_name, f); 192 | } 193 | 194 | public static Tuple LoadSound(string file_name) 195 | { 196 | string path = Path.Combine(ROOT_PATH, SOUND_RESOURCE_PATH, file_name); 197 | SoundBuffer buffer; // = new SoundBuffer(path); 198 | string id_name = GenerateIDFromFilePath(file_name); 199 | buffer = new SoundBuffer(path); 200 | return new Tuple(id_name, buffer); 201 | } 202 | 203 | public static Tuple LoadTexture(string file_name) 204 | { 205 | string path = Path.Combine(ROOT_PATH, TEX_RESOURCE_PATH, file_name); 206 | Texture t = new Texture(path); 207 | t.Smooth = true; 208 | string id_name = GenerateIDFromFilePath(file_name); 209 | 210 | return new Tuple(id_name, t); 211 | } 212 | 213 | /// 214 | /// Just in case inline loader... 215 | /// 216 | /// 217 | /// 218 | public static Texture LoadAndReturnTexture(string file_name) 219 | { 220 | Texture t = new Texture(file_name); 221 | t.Smooth = true; 222 | return t; 223 | } 224 | 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /platformerGame/Camera.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | 11 | namespace platformerGame 12 | { 13 | class Camera 14 | { 15 | /// 16 | /// Center point of the camera 17 | /// 18 | public Vector2f Target; 19 | 20 | /// 21 | /// If we want to move by offset, we can set here 22 | /// 23 | private Vector2f offset; 24 | 25 | /// 26 | /// Toggle for smooth camera transition 27 | /// 28 | public bool Smooth = true; 29 | 30 | /// 31 | /// Smoothness determines how quickly the transition will take place. Higher smoothness will reach the target position faster. 32 | /// 33 | public float Smoothness = 0.1f; //0.033f; 0.1666f 34 | 35 | /// 36 | /// Toggle for automatic position rounding. Useful if pixel sizes become inconsistent or font blurring occurs. 37 | /// 38 | public bool RoundPosition = false; 39 | 40 | public View View; 41 | public Vector2f PreviousPosition; 42 | public Vector2f ActualPosition; 43 | public Vector2f ViewPosition; 44 | private Vector2f originalSize; 45 | 46 | /// 47 | /// Gets or sets the current zoom level of the camera 48 | /// 49 | public float Zoom 50 | { 51 | get { return View.Size.X / originalSize.X; } 52 | set 53 | { 54 | View.Size = originalSize; 55 | View.Zoom(value); 56 | } 57 | } 58 | 59 | /// 60 | /// Calculates the area the camera should display 61 | /// 62 | public AABB Bounds 63 | { 64 | get { return new AABB(ActualPosition.X - (View.Size.X / 2.0f), ActualPosition.Y - (View.Size.Y / 2.0f), View.Size.X, View.Size.Y); } 65 | 66 | } 67 | 68 | public AABB ViewBounds 69 | { 70 | get { return new AABB(ViewPosition - (View.Size / 2.0f), View.Size); } 71 | } 72 | 73 | public Camera(FloatRect rect) : this(new View(rect)) { } 74 | 75 | public Camera(View view) 76 | { 77 | View = new View(view); 78 | Target = View.Size / 2.0f; 79 | originalSize = View.Size; 80 | ActualPosition = Target; 81 | PreviousPosition = ActualPosition; 82 | ViewPosition = ActualPosition; 83 | } 84 | 85 | public void SetOffset(Vector2f offset) 86 | { 87 | this.offset = offset; 88 | } 89 | 90 | /* 91 | public void Move(Vector2f offset) 92 | { 93 | ActualPosition += offset; 94 | } 95 | */ 96 | 97 | public static Vector2f NullVec() 98 | { 99 | return new Vector2f(0.0f, 0.0f); 100 | } 101 | 102 | public void Update(Vector2f target, AABB region_bounds, float step_time = Constants.STEP_TIME) 103 | { 104 | this.Target = target; 105 | PreviousPosition = ActualPosition; 106 | if (Smooth) 107 | { 108 | Vector2f dir = AppMath.Vec2NormalizeReturn(Target - ActualPosition); 109 | float len = (float)AppMath.Vec2Distance(ActualPosition, Target); 110 | Vector2f vel = dir * (len * Smoothness); 111 | //AppMath.Vec2Truncate(ref vel, 2.0f); 112 | //vel += ShakeScreen.Offset; 113 | ActualPosition += vel; 114 | } 115 | else 116 | { 117 | 118 | ActualPosition = Target + ShakeScreen.Offset; 119 | 120 | } 121 | 122 | checkBounds(region_bounds); 123 | } 124 | 125 | /* 126 | public void Apply(RenderTarget target) 127 | { 128 | var center = ActualPosition; 129 | 130 | if (RoundPosition) 131 | { 132 | var pxSize = 1 * Zoom; 133 | center.X = cAppMath.RoundToNearest(ActualPosition.X, pxSize); 134 | center.Y = cAppMath.RoundToNearest(ActualPosition.Y, pxSize); 135 | } 136 | 137 | // offset fixes texture coord rounding 138 | var offset = 0.25f * Zoom; 139 | center.X += offset; 140 | center.Y += offset; 141 | 142 | View.Center = center; 143 | target.SetView(View); 144 | } 145 | */ 146 | 147 | public void LocateActualPosition(Vector2f newPos) 148 | { 149 | ActualPosition = newPos; 150 | PreviousPosition = ActualPosition; 151 | } 152 | 153 | public void checkBounds(AABB region_bounds) 154 | { 155 | var cameraBounds = this.Bounds; 156 | /* 157 | if (RoundPosition) 158 | { 159 | var pxSize = 1 * Zoom; 160 | center.X = cAppMath.RoundToNearest(ActualPosition.X, pxSize); 161 | center.Y = cAppMath.RoundToNearest(ActualPosition.Y, pxSize); 162 | } 163 | */ 164 | 165 | 166 | if (cameraBounds.topLeft.X < region_bounds.topLeft.X) 167 | ActualPosition = new Vector2f(region_bounds.topLeft.X + cameraBounds.halfDims.X, ActualPosition.Y); 168 | else 169 | if (cameraBounds.rightBottom.X > region_bounds.rightBottom.X) 170 | ActualPosition = new Vector2f(region_bounds.rightBottom.X - cameraBounds.halfDims.X, ActualPosition.Y); 171 | 172 | 173 | if (cameraBounds.topLeft.Y < region_bounds.topLeft.Y) 174 | ActualPosition = new Vector2f(ActualPosition.X, region_bounds.topLeft.Y + cameraBounds.halfDims.Y); 175 | else 176 | if (cameraBounds.rightBottom.Y > region_bounds.rightBottom.Y) 177 | ActualPosition = new Vector2f(ActualPosition.X, region_bounds.rightBottom.Y - cameraBounds.halfDims.Y); 178 | 179 | // cameraBounds.SetPosByCenter(ActualPosition); 180 | } 181 | 182 | public void DeployOn(RenderTarget target, float alpha, AABB region_bounds = null) 183 | { 184 | 185 | /* 186 | // offset fixes texture coord rounding 187 | var offset = 0.25f * Zoom; 188 | center.X += offset; 189 | center.Y += offset; 190 | */ 191 | //Target = center; 192 | //ActualPosition = center; 193 | this.ViewPosition = AppMath.Interpolate(ActualPosition, PreviousPosition, alpha); 194 | this.View.Center = this.ViewPosition; 195 | target.SetView(this.View); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /platformerGame/Containers/GridOccupant.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.System; 7 | 8 | namespace platformerGame.Containers 9 | { 10 | abstract class GridOccupant 11 | { 12 | public AABB Bounds { get; set; } = new AABB(0, 0, 1, 1); 13 | public Vector2i GridPosition { get; set; } = new Vector2i(0, 0); 14 | 15 | public GridOccupant() 16 | { 17 | } 18 | 19 | public GridOccupant(AABB _bounds) 20 | { 21 | Bounds = _bounds.ShallowCopy(); 22 | } 23 | 24 | public virtual void Update(float step_time) 25 | { } 26 | 27 | public virtual bool isActive() 28 | { 29 | return true; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /platformerGame/Containers/IPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Containers 8 | { 9 | interface IPool 10 | { 11 | List ListVisibles(AABB visible_region); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /platformerGame/Containers/cQuadTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | 10 | using platformerGame.Utilities; 11 | using platformerGame.App; 12 | 13 | namespace platformerGame.Containers 14 | { 15 | class cQuadTree where T : GridOccupant 16 | { 17 | public const int MAX_OBJECTS = 10; 18 | public const int MAX_LEVEL = 4; 19 | 20 | List entities; 21 | 22 | static int numLevels = 0; 23 | int level; 24 | AABB bounds; 25 | 26 | RectangleShape shape; 27 | Text label; 28 | //cQuadTree* m_pParent; 29 | 30 | cQuadTree pNW; //north-west : left-top 31 | cQuadTree pNE; //north-east : right-top 32 | cQuadTree pSW; //south-west : left-bottom 33 | cQuadTree pSE; //south-east : right-bottom 34 | 35 | //sfml text 36 | //Text m_Text; 37 | GameState refState; 38 | 39 | public cQuadTree(int _level, AABB _bounds, GameState state) 40 | { 41 | this.refState = state; 42 | this.level = _level; 43 | this.bounds = _bounds; 44 | 45 | this.shape = new RectangleShape(bounds.dims); 46 | this.shape.Position = bounds.topLeft; 47 | this.shape.OutlineColor = Color.Red; 48 | this.shape.FillColor = Color.Transparent; 49 | this.shape.OutlineThickness = 1.0f; 50 | 51 | entities = new List(); 52 | 53 | label = new Text(); 54 | 55 | float xPos = bounds.rightBottom.X - level * 50; 56 | label.Position = new Vector2f(xPos, bounds.rightBottom.Y - 30); 57 | 58 | 59 | label.Font = state.Assets.GetFont("BGOTHL"); 60 | label.CharacterSize = 24; 61 | label.Color = Color.White; 62 | label.Style = Text.Styles.Bold; 63 | 64 | SplitToRects(); 65 | } 66 | 67 | public AABB Bounds 68 | { 69 | get { return bounds; } 70 | //set { bounds = value; } 71 | } 72 | 73 | public void SplitToRects() 74 | { 75 | if (level >= MAX_LEVEL) 76 | { 77 | return; 78 | } 79 | 80 | numLevels++; 81 | 82 | float subWidth = bounds.halfDims.X; 83 | float subHeight = bounds.halfDims.Y; 84 | float x = bounds.topLeft.X; 85 | float y = bounds.topLeft.Y; 86 | 87 | pNW = new cQuadTree(level + 1, new AABB(new Vector2f(x, y), new Vector2f(subWidth, subHeight)), refState); 88 | pNE = new cQuadTree(level + 1, new AABB(new Vector2f(x + subWidth, y), new Vector2f(subWidth, subHeight)), refState); 89 | pSW = new cQuadTree(level + 1, new AABB(new Vector2f(x, y + subHeight), new Vector2f(subWidth, subHeight)), refState); 90 | pSE = new cQuadTree(level + 1, new AABB(new Vector2f(x + subWidth, y + subHeight), new Vector2f(subWidth, subHeight)), refState); 91 | 92 | } 93 | 94 | public void Clear() 95 | { 96 | if (level == MAX_LEVEL) 97 | { 98 | entities.Clear(); 99 | return; 100 | } 101 | else 102 | //if(this.level + 1 <= numLevels) 103 | { 104 | pNW.Clear(); 105 | pNE.Clear(); 106 | pSW.Clear(); 107 | pSE.Clear(); 108 | } 109 | 110 | if (entities.Count > 0) 111 | { 112 | entities.Clear(); 113 | } 114 | } 115 | 116 | public bool Contains(cQuadTree child, T entity) 117 | { 118 | //bool b = (cCollision.OverlapAABB(child.Bounds, entity.Bounds)); 119 | //bool b = pChild->GetBounds().AsFloatRect().intersects(pEntity->GetBoundingBox().AsFloatRect()); 120 | return cCollision.OverlapAABB(child.Bounds, entity.Bounds); 121 | } 122 | 123 | public void AddEntity(T entity) 124 | { 125 | /* 126 | if (entities.Count >= MAX_OBJECTS) 127 | { 128 | SplitToRects(); 129 | } 130 | */ 131 | 132 | if (level >= MAX_LEVEL) 133 | { 134 | entities.Add(entity); 135 | return; 136 | } 137 | 138 | 139 | if (Contains(pNW, entity)) 140 | { 141 | pNW.AddEntity(entity); 142 | //return; 143 | } 144 | 145 | if (Contains(pNE, entity)) 146 | { 147 | pNE.AddEntity(entity); 148 | //return; 149 | } 150 | 151 | if (Contains(pSW, entity)) 152 | { 153 | pSW.AddEntity(entity); 154 | //return; 155 | } 156 | 157 | if (Contains(pSE, entity)) 158 | { 159 | pSE.AddEntity(entity); 160 | //return; 161 | } 162 | 163 | /* 164 | if (Contains(this, entity)) //contains 165 | { 166 | //logger << "Entity added to tree" << ""; 167 | entities.Add(entity); 168 | //m_Text.setString( StringOf(m_Entities.size()) ); 169 | } 170 | */ 171 | 172 | 173 | } 174 | public List GetEntitiesAtPos(Vector2f pos) 175 | { 176 | if (level == MAX_LEVEL) 177 | return entities; 178 | 179 | List returnEntities = new List(); 180 | List childReturnEntities = new List(); 181 | 182 | FloatRect boundsRect = bounds.AsSfmlFloatRect(); 183 | 184 | if (entities.Count > 0) 185 | { 186 | returnEntities = entities; 187 | } 188 | 189 | if (pos.X > boundsRect.Left + boundsRect.Width / 2.0f && pos.X < boundsRect.Left + boundsRect.Width) 190 | { 191 | if (pos.Y > boundsRect.Top + boundsRect.Height / 2.0f && pos.Y < boundsRect.Top + boundsRect.Height) 192 | { 193 | childReturnEntities = pSE.GetEntitiesAtPos(pos); 194 | 195 | returnEntities.AddRange(childReturnEntities); 196 | 197 | return returnEntities; 198 | } 199 | else 200 | if (pos.Y > boundsRect.Top && pos.Y <= boundsRect.Top + boundsRect.Height / 2.0f) 201 | { 202 | childReturnEntities = pNE.GetEntitiesAtPos(pos); 203 | returnEntities.AddRange(childReturnEntities); 204 | return returnEntities; 205 | } 206 | } 207 | else 208 | if (pos.X > boundsRect.Left && pos.X <= boundsRect.Left + boundsRect.Width / 2.0f) 209 | { 210 | if (pos.Y > boundsRect.Top + boundsRect.Height / 2.0f && pos.Y < boundsRect.Top + boundsRect.Height) 211 | { 212 | childReturnEntities = pSW.GetEntitiesAtPos(pos); 213 | returnEntities.AddRange(childReturnEntities); 214 | return returnEntities; 215 | } 216 | else 217 | if (pos.Y > boundsRect.Top && pos.Y <= boundsRect.Top + boundsRect.Height / 2.0f) 218 | { 219 | childReturnEntities = pNW.GetEntitiesAtPos(pos); 220 | returnEntities.AddRange(childReturnEntities); 221 | return returnEntities; 222 | } 223 | } 224 | 225 | return returnEntities; 226 | } 227 | 228 | public void DrawBounds(RenderTarget target) 229 | { 230 | label.DisplayedString = this.entities.Count.ToString(); 231 | target.Draw(this.shape, new RenderStates(BlendMode.Alpha)); 232 | target.Draw(label); 233 | 234 | if(this.level < MAX_LEVEL) 235 | { 236 | pNW.DrawBounds(target); 237 | pNE.DrawBounds(target); 238 | pSW.DrawBounds(target); 239 | pSE.DrawBounds(target); 240 | } 241 | } 242 | 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /platformerGame/Containers/cSpatialCell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Containers 8 | { 9 | class cSpatialCell 10 | { 11 | List objects; // IDs of the stored objects 12 | 13 | int cellIndex; // the index of this cell in the spatial grid 14 | 15 | /* 16 | int gridX, gridY; 17 | cAABB bounds; 18 | */ 19 | 20 | public cSpatialCell() 21 | { 22 | cellIndex = 0; 23 | objects = new List(); 24 | } 25 | 26 | public cSpatialCell(int cell_index) 27 | { 28 | this.cellIndex = cell_index; 29 | objects = new List(); 30 | } 31 | 32 | public void clear() 33 | { 34 | objects.Clear(); 35 | } 36 | 37 | public void add(int object_id) 38 | { 39 | if(false == objects.Contains(object_id)) 40 | objects.Add(object_id); 41 | } 42 | 43 | public void remove(int object_id) 44 | { 45 | objects.Remove(object_id); 46 | } 47 | 48 | public int[] getAll() 49 | { 50 | return objects.ToArray(); 51 | } 52 | 53 | 54 | public int CellIndex 55 | { 56 | get { return cellIndex; } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /platformerGame/Containers/cSpatialGrid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.System; 7 | 8 | namespace platformerGame.Containers 9 | { 10 | class cSpatialGrid 11 | { 12 | const int CELL_SIZE = 128; // 128 X 128 square 13 | 14 | cSpatialCell[] grid; 15 | 16 | Dictionary> cells; 17 | 18 | int height; 19 | int width; 20 | int numCells; 21 | 22 | public cSpatialGrid(int w, int h) 23 | { 24 | this.width = w; 25 | this.height = h; 26 | this.numCells = w * h; 27 | this.grid = new cSpatialCell[numCells]; 28 | initCells(); 29 | } 30 | 31 | public cSpatialGrid(Vector2f world_size) 32 | { 33 | this.width = (int)world_size.X / CELL_SIZE; 34 | this.height = (int)world_size.Y / CELL_SIZE; 35 | this.numCells = width * height; 36 | this.grid = new cSpatialCell[numCells]; 37 | initCells(); 38 | 39 | } 40 | 41 | private void initCells() 42 | { 43 | for(int i = 0; i < grid.Length; ++i) 44 | { 45 | grid[i] = new cSpatialCell(i); 46 | } 47 | } 48 | public void ClearAll() 49 | { 50 | foreach (var cell in grid) 51 | { 52 | cell.clear(); 53 | } 54 | } 55 | 56 | public int GetIndexByXY(int x, int y) 57 | { 58 | int index = y * width + x; 59 | return index; 60 | } 61 | 62 | public int GetIndexByXY(Vector2i grid_pos) 63 | { 64 | int index = grid_pos.Y * width + grid_pos.X; 65 | return index; // index < 0 ? 0 : index >= numCells ? numCells -1 : index; 66 | } 67 | 68 | public cSpatialCell GetCellAtXY(int grid_x, int grid_y) 69 | { 70 | int index = grid_y * width + grid_x; 71 | return index >= 0 && index < numCells ? grid[index] : null; 72 | } 73 | 74 | public int GetCellIndexAtWorldPos(Vector2f world_pos) 75 | { 76 | Vector2i gridPos = ToGridPos(world_pos); 77 | return GetIndexByXY(gridPos); 78 | } 79 | 80 | public cSpatialCell getCell(Vector2f world_pos) 81 | { 82 | Vector2i gridPos = ToGridPos(world_pos); 83 | int index = GetIndexByXY(gridPos); 84 | return grid[index]; 85 | } 86 | 87 | public Vector2i ToGridPos(Vector2f world_pos) 88 | { 89 | Vector2i ret = new Vector2i(); 90 | ret.X = (int)(world_pos.X / CELL_SIZE); 91 | ret.Y = (int)(world_pos.Y / CELL_SIZE); 92 | 93 | ret.X = ret.X >= width ? width - 1 : ret.X < 0 ? 0 : ret.X; 94 | ret.Y = ret.Y >= height ? height - 1 : ret.Y < 0 ? 0 : ret.Y; 95 | return ret; 96 | } 97 | 98 | public Vector2f ToWorldPos(Vector2i grid_pos) 99 | { 100 | Vector2f ret = new Vector2f(); 101 | ret.X = grid_pos.X * CELL_SIZE; 102 | ret.Y = grid_pos.Y * CELL_SIZE; 103 | return ret; 104 | } 105 | 106 | public void DeHandleObject(int id, AABB last_bounds) 107 | { 108 | 109 | } 110 | 111 | public void GetCells() 112 | { 113 | } 114 | 115 | public void HandleObject(int id, AABB bounds) 116 | { 117 | int topLeftIndex = GetCellIndexAtWorldPos(bounds.topLeft); 118 | int topRightIndex = GetCellIndexAtWorldPos(bounds.getTopRight()); 119 | int bottomRightIndex = GetCellIndexAtWorldPos(bounds.rightBottom); 120 | int bottomLeftIndex = GetCellIndexAtWorldPos(bounds.getLeftBottom()); 121 | 122 | 123 | if (topLeftIndex == bottomRightIndex) 124 | { 125 | grid[topLeftIndex].add(id); 126 | } 127 | else 128 | { 129 | if (topLeftIndex == bottomLeftIndex || bottomLeftIndex == bottomRightIndex) 130 | { 131 | grid[topLeftIndex].add(id); 132 | grid[bottomRightIndex].add(id); 133 | } 134 | else 135 | { 136 | grid[topLeftIndex].add(id); 137 | grid[topRightIndex].add(id); 138 | grid[bottomRightIndex].add(id); 139 | grid[bottomLeftIndex].add(id); 140 | } 141 | } 142 | } 143 | 144 | public int[] getObjectsAtWorldPos(Vector2f world_pos) 145 | { 146 | return getCell(world_pos)?.getAll(); 147 | } 148 | 149 | public int[] getObjectsAtGridPos(int grid_x, int grid_y) 150 | { 151 | return GetCellAtXY(grid_x, grid_y)?.getAll(); 152 | } 153 | 154 | public int[] getPossibleCollidableObjects(AABB bounds) 155 | { 156 | List all = new List(); 157 | int topLeftIndex = GetCellIndexAtWorldPos(bounds.topLeft); 158 | int topRightIndex = GetCellIndexAtWorldPos(bounds.getTopRight()); 159 | int bottomRightIndex = GetCellIndexAtWorldPos(bounds.rightBottom); 160 | int bottomLeftIndex = GetCellIndexAtWorldPos(bounds.getLeftBottom()); 161 | 162 | if (topLeftIndex == bottomRightIndex) 163 | { 164 | all.AddRange(grid[topLeftIndex].getAll()); 165 | } 166 | else 167 | { 168 | if (topLeftIndex == bottomLeftIndex || bottomLeftIndex == bottomRightIndex) 169 | { 170 | all.AddRange(grid[topLeftIndex].getAll()); 171 | all.AddRange(grid[bottomRightIndex].getAll()); 172 | } 173 | else 174 | { 175 | all.AddRange(grid[topLeftIndex].getAll()); 176 | all.AddRange(grid[topRightIndex].getAll()); 177 | all.AddRange(grid[bottomRightIndex].getAll()); 178 | all.AddRange(grid[bottomLeftIndex].getAll()); 179 | } 180 | } 181 | return all.ToArray(); 182 | } 183 | 184 | 185 | public int[] getPossibleCollidableObjectsWithAdjacents(Vector2f position) 186 | { 187 | List all = new List(); 188 | Vector2i gridPos = ToGridPos(position); 189 | int[] objs; 190 | 191 | if(null != (objs = getObjectsAtGridPos(gridPos.X - 1, gridPos.Y - 1))) 192 | { 193 | all.AddRange(objs); 194 | } 195 | 196 | if (null != (objs = getObjectsAtGridPos(gridPos.X, gridPos.Y - 1))) 197 | { 198 | all.AddRange(objs); 199 | } 200 | 201 | if (null != (objs = getObjectsAtGridPos(gridPos.X + 1, gridPos.Y - 1))) 202 | { 203 | all.AddRange(objs); 204 | } 205 | 206 | if (null != (objs = getObjectsAtGridPos(gridPos.X - 1, gridPos.Y))) 207 | { 208 | all.AddRange(objs); 209 | } 210 | 211 | if (null != (objs = getObjectsAtGridPos(gridPos.X, gridPos.Y))) 212 | { 213 | all.AddRange(objs); 214 | } 215 | 216 | if (null != (objs = getObjectsAtGridPos(gridPos.X + 1, gridPos.Y))) 217 | { 218 | all.AddRange(objs); 219 | } 220 | 221 | if (null != (objs = getObjectsAtGridPos(gridPos.X - 1, gridPos.Y + 1))) 222 | { 223 | all.AddRange(objs); 224 | } 225 | 226 | if (null != (objs = getObjectsAtGridPos(gridPos.X, gridPos.Y + 1))) 227 | { 228 | all.AddRange(objs); 229 | } 230 | 231 | if (null != (objs = getObjectsAtGridPos(gridPos.X + 1, gridPos.Y + 1))) 232 | { 233 | all.AddRange(objs); 234 | } 235 | 236 | return all.ToArray(); 237 | } 238 | 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /platformerGame/Effects/EffectSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.System; 7 | using SFML.Graphics; 8 | using platformerGame.Rendering; 9 | 10 | namespace platformerGame.Effects 11 | { 12 | class AnimatedEffect 13 | { 14 | public Vector2f Centre { get; set; } // centre 15 | public cAnimation Animation { get; set; } 16 | 17 | public AnimatedEffect() 18 | { 19 | this.Centre = new Vector2f(); 20 | this.Animation = null; 21 | } 22 | } 23 | 24 | class EffectSystem 25 | { 26 | List effects; 27 | 28 | public EffectSystem() 29 | { 30 | effects = new List(); 31 | } 32 | 33 | public void Place(AnimatedEffect effect) 34 | { 35 | this.effects.Add(effect); 36 | } 37 | 38 | public void Place(Vector2f centre, string animation_name, bool repeat = false) 39 | { 40 | var effect = new AnimatedEffect(); 41 | effect.Animation = new cAnimation(cAnimationAssets.Get(animation_name)); 42 | effect.Animation.AnimData.Repeat = repeat; 43 | effect.Centre = centre; 44 | this.Place(effect); 45 | } 46 | 47 | public void PlaceGround(float x, float groundY, string animation_name) 48 | { 49 | var effect = new AnimatedEffect(); 50 | effect.Animation = new cAnimation(cAnimationAssets.Get(animation_name)); 51 | 52 | int h = effect.Animation.AnimData.ViewOffsetRect.Height; 53 | effect.Centre = new Vector2f(x, groundY - (h / 2.0f)); 54 | this.Place(effect); 55 | } 56 | 57 | public void Update() 58 | { 59 | int eCount = effects.Count; 60 | for (int i = 0; i < eCount; ++i) 61 | { 62 | var e = effects[i]; 63 | 64 | if (e.Animation.Active) 65 | { 66 | e.Animation.Update(); 67 | continue; 68 | } 69 | 70 | effects.RemoveAt(i); 71 | i--; 72 | eCount = effects.Count; 73 | 74 | } 75 | } 76 | 77 | public void Render(RenderTarget destination) 78 | { 79 | foreach (var e in effects) 80 | { 81 | e.Animation.RenderCentered(destination, e.Centre); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/Bird.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.GameObjects 8 | { 9 | class Bird : cGameObject 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/EntityGrid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | using platformerGame.Containers; 11 | 12 | namespace platformerGame.GameObjects 13 | { 14 | 15 | class EntityGrid where T : GridOccupant 16 | { 17 | public const int ENTITY_GRID_SIZE = 128; 18 | public const int ENTITY_OVERSCAN = 128; 19 | 20 | protected List allEntities; 21 | //protected List visibleEntities; // on screen 22 | 23 | protected Dictionary> entityGrid; 24 | protected float cleanupTimer = 0.0f; 25 | 26 | public AABB GridArea { get; set; } 27 | 28 | public EntityGrid(Vector2f world_size) 29 | { 30 | GridArea = new AABB(0.0f, 0.0f, world_size.X, world_size.Y); 31 | this.initGrid(); 32 | } 33 | 34 | public EntityGrid(AABB grid_bounds) 35 | { 36 | GridArea = grid_bounds; 37 | this.initGrid(); 38 | } 39 | 40 | protected void initGrid() 41 | { 42 | this.allEntities = new List(); 43 | //this.visibleEntities = new List(); 44 | this.entityGrid = new Dictionary>(); 45 | } 46 | 47 | public static Vector2i calcGridPos(Vector2f world_pos) 48 | { 49 | int x = (int)world_pos.X / ENTITY_GRID_SIZE; 50 | int y = (int)world_pos.Y / ENTITY_GRID_SIZE; 51 | return new Vector2i(x, y); 52 | } 53 | 54 | public List getInGridRect(int startX, int startY, int endX, int endY) 55 | { 56 | var pos = new Vector2i(); 57 | 58 | List returner = new List(); 59 | 60 | for (var y = startY; y <= endY; y++) 61 | { 62 | for (var x = startX; x <= endX; x++) 63 | { 64 | pos.X = x; 65 | pos.Y = y; 66 | 67 | List list; 68 | if (entityGrid.TryGetValue(pos, out list)) 69 | { 70 | returner.AddRange(list); 71 | } 72 | } 73 | } 74 | 75 | return returner; 76 | } 77 | 78 | public List getEntitiesInRadius(Vector2f centre, float radius) 79 | { 80 | float sideLen = 2.0f * radius; 81 | AABB circleBoundRect = new AABB(); 82 | circleBoundRect.SetDims(new Vector2f(sideLen, sideLen)); 83 | circleBoundRect.SetPosByCenter(centre); 84 | 85 | return getEntitiesInArea(circleBoundRect); 86 | } 87 | 88 | public List getEntitiesNearby(Vector2f pos) 89 | { 90 | Vector2i gridPos = calcGridPos(pos); 91 | return this.getInGridRect(gridPos.X - 1, gridPos.Y - 1, gridPos.X + 1, gridPos.Y + 1); 92 | } 93 | 94 | public List getEntitiesInArea(AABB area) 95 | { 96 | FloatRect areaRect = area.AsSfmlFloatRect(); 97 | 98 | var overscan = ENTITY_OVERSCAN; 99 | var gridSize = ENTITY_GRID_SIZE; 100 | 101 | FloatRect rect = new FloatRect(areaRect.Left - overscan, areaRect.Top - overscan, 102 | areaRect.Width + (overscan * 2), areaRect.Height + (overscan * 2)); 103 | 104 | var startX = (int)rect.Left / gridSize; 105 | var startY = (int)rect.Top / gridSize; 106 | var width = (int)rect.Width / gridSize + 1; 107 | var height = (int)rect.Height / gridSize + 1; 108 | 109 | return this.getInGridRect(startX, startY, startX + width, startY + height); 110 | } 111 | 112 | public List GetAllEntities() 113 | { 114 | return this.allEntities; 115 | } 116 | 117 | public void AddEntities(IEnumerable entities) 118 | { 119 | foreach(var e in entities) 120 | { 121 | this.allEntities.Add(e); 122 | this.GridAdd(e); 123 | } 124 | } 125 | 126 | public void AddEntity(T e) 127 | { 128 | this.allEntities.Add(e); 129 | this.GridAdd(e); 130 | } 131 | 132 | public void RemoveEntity(T e) 133 | { 134 | // e.Destroy(); 135 | 136 | GridRemove(e); 137 | this.allEntities.Remove(e); 138 | } 139 | 140 | public void RemoveAll() 141 | { 142 | foreach (var e in this.entityGrid) 143 | { 144 | e.Value.Clear(); 145 | } 146 | 147 | this.entityGrid.Clear(); 148 | this.allEntities.Clear(); 149 | } 150 | 151 | protected void checkForCleanup(float step_time) 152 | { 153 | // cleanup grid 154 | cleanupTimer += step_time; 155 | // System.Diagnostics.Debug.WriteLine(cleanupTimer); 156 | 157 | if (cleanupTimer >= 6.0f) 158 | { 159 | entityGrid.RemoveAll(kv => kv.Value.Count == 0); 160 | cleanupTimer = 0.0f; 161 | } 162 | } 163 | 164 | protected void gridHandleUpdate(float step_time) 165 | { 166 | // update all entites 167 | Vector2i newGridPos = new Vector2i(0, 0); 168 | 169 | int eCount = allEntities.Count; 170 | for (int i = 0; i < eCount; ++i) 171 | { 172 | T entity = allEntities[i]; 173 | 174 | if (entity.isActive()) 175 | { 176 | 177 | // updateFunc?.Invoke(entity, step_time); 178 | 179 | entity.Update(step_time); 180 | 181 | var bounds = entity.Bounds; 182 | newGridPos = calcGridPos(bounds.center); 183 | 184 | if (!entity.GridPosition.Equals(newGridPos)) 185 | { 186 | GridRemove(entity); 187 | entity.GridPosition = newGridPos; 188 | GridAdd(entity); 189 | } 190 | 191 | continue; 192 | } 193 | 194 | GridRemove(entity); 195 | allEntities.RemoveAt(i); 196 | i--; 197 | eCount = allEntities.Count; 198 | } 199 | } 200 | 201 | public virtual void Update(float step_time) 202 | { 203 | this.gridHandleUpdate(step_time); 204 | this.checkForCleanup(step_time); 205 | } 206 | 207 | protected void GridAdd(T e) 208 | { 209 | List list; 210 | 211 | if (false == entityGrid.TryGetValue(e.GridPosition, out list)) 212 | { 213 | list = new List(); 214 | list.Add(e); 215 | entityGrid.Add(e.GridPosition, list); 216 | return; 217 | } 218 | 219 | list.Add(e); 220 | } 221 | 222 | protected bool GridRemove(T e) 223 | { 224 | List list; 225 | 226 | if (entityGrid.TryGetValue(e.GridPosition, out list)) 227 | { 228 | return list.Remove(e); 229 | } 230 | 231 | 232 | #if DEBUG 233 | System.Diagnostics.Debug.WriteLine( 234 | string.Format("Remove - FALSE")); 235 | #endif 236 | 237 | return false; 238 | } 239 | 240 | /// 241 | /// Filters visible entites and performs view position calculation for the visible ones. 242 | /// 243 | /// 244 | public IEnumerable filterVisibles(AABB view_region, Action executeOnTrue = null) 245 | { 246 | return this.allEntities.Where( e => 247 | { 248 | executeOnTrue?.Invoke(e); 249 | return cCollision.OverlapAABB(e.Bounds, view_region); 250 | } 251 | ); 252 | 253 | /* 254 | foreach (var e in allEntities) 255 | { 256 | if (cCollision.OverlapAABB(e.Bounds, view_region)) 257 | { 258 | // e.CalculateViewPos(alpha); 259 | yield return e; 260 | } 261 | } 262 | */ 263 | } 264 | } 265 | 266 | } 267 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/PickupInfo/cPickupInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | using platformerGame.Rendering; 11 | 12 | namespace platformerGame.GameObjects.PickupInfo 13 | { 14 | delegate void PickupEffectFunction(cPlayer player); 15 | 16 | enum PickupType 17 | { 18 | UNKNOWN = -1, 19 | HEALTH = 0, 20 | ARMOR, 21 | AMMO, 22 | COIN_GOLD, 23 | COIN_SILVER, 24 | COIN_IRON 25 | } 26 | 27 | 28 | class cPickupInfo 29 | { 30 | PickupType pickupType; 31 | cBaseRenderer renderer; 32 | Vector2f hitRectSize; 33 | PickupEffectFunction effect; 34 | 35 | 36 | public cPickupInfo() 37 | { 38 | this.pickupType = PickupType.UNKNOWN; 39 | this.renderer = null; 40 | this.hitRectSize = new Vector2f(0, 0); 41 | this.effect = null; 42 | } 43 | 44 | public cPickupInfo(PickupType pickup_type, cBaseRenderer renderer, Vector2f hit_rect_size, PickupEffectFunction effect) 45 | { 46 | this.pickupType = pickup_type; 47 | this.renderer = renderer; 48 | this.hitRectSize = hit_rect_size; 49 | this.effect = effect; 50 | } 51 | 52 | public void applyEffect(cPlayer player) 53 | { 54 | effect(player); 55 | } 56 | 57 | public cPickupInfo ShallowCopy() 58 | { 59 | return (cPickupInfo)this.MemberwiseClone(); 60 | } 61 | 62 | /* 63 | public cPickupInfo DeepCopy() 64 | { 65 | cPickupInfo copy = this.ShallowCopy(); 66 | 67 | return copy; 68 | } 69 | */ 70 | 71 | public PickupType PickupType 72 | { 73 | get { return pickupType; } 74 | } 75 | 76 | public cBaseRenderer Renderer 77 | { 78 | get { return renderer; } 79 | } 80 | 81 | public PickupEffectFunction Effect 82 | { 83 | get { return effect; } 84 | } 85 | 86 | public Vector2f HitRectSize 87 | { 88 | get { return this.hitRectSize; } 89 | } 90 | } 91 | 92 | class PickupEffects 93 | { 94 | 95 | private static Dictionary pickupTypes; 96 | 97 | private static ProbabilityRoll roller; 98 | 99 | private static Tuple[] pickupProbabilityTable; 100 | 101 | static PickupEffects() 102 | { 103 | 104 | } 105 | 106 | public static void Cleanup() 107 | { 108 | pickupTypes.Clear(); 109 | roller.clear(); 110 | } 111 | 112 | public static void InitPickupEffects(AssetContext assets) 113 | { 114 | /* 115 | int[] tcoords = { 0, 24, 48 }; 116 | int tx = AppRandom.Chooose(tcoords); 117 | int ty = AppRandom.Chooose(tcoords, 2); 118 | */ 119 | pickupTypes = new Dictionary() 120 | { 121 | [PickupType.HEALTH] = new cPickupInfo(PickupType.HEALTH, new cSpriteRenderer("pickups", new MyIntRect(0, 0, 24, 24), assets), new Vector2f(16, 22), AddHealth), 122 | [PickupType.ARMOR] = new cPickupInfo(PickupType.ARMOR, new cSpriteRenderer("pickups", new MyIntRect(0, 24, 24, 24), assets), new Vector2f(16, 22), AddArmor), 123 | [PickupType.AMMO] = new cPickupInfo(PickupType.AMMO, new cSpriteRenderer("pickups", new MyIntRect(24, 0, 24, 24), assets), new Vector2f(16, 22), AddAmmo), 124 | [PickupType.COIN_GOLD] = new cPickupInfo(PickupType.COIN_GOLD, new cAnimatedSpriteRenderer("coins-gold", new MyIntRect(0, 0, 16, 16), true), new Vector2f(16, 16), AddCoin), 125 | [PickupType.COIN_SILVER] = new cPickupInfo(PickupType.COIN_SILVER, new cAnimatedSpriteRenderer("coins-silver", new MyIntRect(0, 0, 16, 16), true), new Vector2f(16, 16), AddCoin), 126 | [PickupType.COIN_IRON] = new cPickupInfo(PickupType.COIN_IRON, new cAnimatedSpriteRenderer("coins-copper", new MyIntRect(0, 0, 16, 16), true), new Vector2f(16, 16), AddCoin) 127 | }; 128 | 129 | pickupProbabilityTable = new Tuple[4] 130 | { 131 | new Tuple(50, PickupType.HEALTH), 132 | new Tuple(5, PickupType.ARMOR), 133 | new Tuple(5, PickupType.AMMO), 134 | new Tuple(40, PickupType.COIN_GOLD) 135 | }; 136 | 137 | roller = new ProbabilityRoll(); 138 | roller.seed(pickupProbabilityTable); 139 | } 140 | 141 | public static cPickupInfo get(PickupType type) 142 | { 143 | return pickupTypes[type]; 144 | } 145 | 146 | public static cPickupInfo getWeighted() 147 | { 148 | return get( roller.roll() ).ShallowCopy(); 149 | } 150 | 151 | private static void AddHealth(cPlayer player) 152 | { 153 | player.Health += 1; 154 | } 155 | 156 | private static void AddArmor(cPlayer player) 157 | { 158 | player.Health += 1; 159 | } 160 | 161 | private static void AddAmmo(cPlayer player) 162 | { 163 | player.Health += 1; 164 | } 165 | 166 | private static void AddCoin(cPlayer player) 167 | { 168 | player.Scene.Assets.PlaySound("coin_pickup1", 10); 169 | // TODO: player.Money += 1; 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/cBullet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | 10 | using platformerGame.Utilities; 11 | 12 | namespace platformerGame.GameObjects 13 | { 14 | class BulletBreed 15 | { 16 | public Sprite sprite; 17 | public float startSpeed; 18 | public uint textureIntersectionOffset; 19 | public uint slugLength; 20 | 21 | public static Dictionary breeds; 22 | 23 | public BulletBreed() 24 | { } 25 | 26 | // must call somewhere 27 | public static void Init(AssetContext assets) 28 | { 29 | breeds = new Dictionary(); 30 | 31 | BulletBreed b = new BulletBreed() 32 | { 33 | sprite = new Sprite( assets.GetTexture("bullet_light_green")), 34 | startSpeed = Constants.BULLET_START_SPEED, 35 | textureIntersectionOffset = 30, 36 | slugLength = 5 37 | }; 38 | 39 | b.sprite.Scale = new Vector2f(0.5f, 0.5f); 40 | b.sprite.Origin = new Vector2f(b.sprite.TextureRect.Width - b.textureIntersectionOffset, b.sprite.TextureRect.Height / 2.0f); 41 | breeds.Add("simple-bullet", b); 42 | 43 | BulletBreed b2 = new BulletBreed() 44 | { 45 | sprite = new Sprite( assets.GetTexture("bullet3")), 46 | startSpeed = 250, 47 | textureIntersectionOffset = 1, 48 | slugLength = 1 49 | }; 50 | 51 | b2.sprite.Scale = new Vector2f(0.7f, 0.7f); 52 | b2.sprite.Origin = new Vector2f(b2.sprite.TextureRect.Width, b2.sprite.TextureRect.Height / 2.0f); 53 | 54 | breeds.Add("turret-bullet", b2); 55 | } 56 | 57 | public static BulletBreed GetBreed(string id) 58 | { 59 | BulletBreed b; 60 | if(breeds.TryGetValue(id, out b)) 61 | { 62 | return b; 63 | } 64 | 65 | return null; 66 | } 67 | 68 | public static void Cleanup() 69 | { 70 | breeds.Clear(); 71 | } 72 | } 73 | 74 | class cBullet : cGameObject 75 | { 76 | const uint SLUG_LENGTH = 5; 77 | 78 | // 30, 15 pixels from the edge of the texture 79 | const uint TEXTURE_INTERSECTION_OFFSET = 30; 80 | 81 | BulletBreed breed; 82 | 83 | RenderStates blendMode = new RenderStates(BlendMode.Add); 84 | 85 | protected cGameObject owner; 86 | protected Vector2f oppositeDir; 87 | protected Vector2f intersection; 88 | 89 | protected Sprite sprite; 90 | protected bool alive; 91 | protected float alpha; 92 | 93 | /// 94 | /// 95 | /// 96 | /// 97 | /// position 98 | /// owner gameobject ex. cCharacter 99 | /// normalized vector of direction 100 | public cBullet(cGameObject owner, BulletBreed breed, Vector2f pos, Vector2f direction) : base(owner.Scene, pos) 101 | { 102 | this.owner = owner; 103 | this.breed = breed; 104 | 105 | this.alive = true; 106 | this.alpha = 255.0f; 107 | // proci határozza meg, hogy milyen alaplap foglalat és milyen RAM!! 108 | this.heading = direction; 109 | this.Bounds = new AABB(); 110 | this.Bounds.SetDims(new Vector2f(1.0f, 1.0f)); 111 | this.oppositeDir = new Vector2f(-this.heading.X * breed.slugLength, -this.heading.Y * breed.slugLength); 112 | this.intersection = new Vector2f(0.0f, 0.0f); 113 | this.Bounds.SetPosByTopLeft(pos); 114 | this.velocity.X = this.heading.X * breed.startSpeed; 115 | this.velocity.Y = this.heading.Y * breed.startSpeed; 116 | orientation = AppMath.GetAngleOfVector(heading); 117 | 118 | this.sprite = new Sprite(this.breed.sprite); // bullet_yellow_sm; bullet_light_gree 119 | this.sprite.Rotation = (float)AppMath.RadianToDegress(this.orientation); 120 | } 121 | 122 | public cGameObject Owner 123 | { 124 | get { return owner; } 125 | } 126 | 127 | public bool checkCollisionWithWorld(cWorld world, ref Vector2f intersectionOut) 128 | { 129 | Vector2i posA = new Vector2i((int)this.lastPosition.X, (int)this.lastPosition.Y); //world.ToMapPos(this.lastPosition); 130 | Vector2i posB = new Vector2i((int)this.position.X, (int)this.position.Y); // world.ToMapPos(this.Position); 131 | bool collided = false; 132 | 133 | Vector2f intersectionPoint = new Vector2f(0.0f, 0.0f); 134 | AppMath.Raytrace(posA.X, posA.Y, posB.X, posB.Y, 135 | (x, y) => 136 | { 137 | 138 | collided = world.IsWallAtPos(new Vector2f(x, y)); //world.GetCurrentLevel.IsObstacleAtPos(x, y); 139 | 140 | intersectionPoint.X = x; // = world.ToWorldPos(new Vector2i(x, y)); 141 | intersectionPoint.Y = y; 142 | 143 | 144 | return collided; 145 | } 146 | ); 147 | 148 | intersectionOut.X = intersectionPoint.X; 149 | intersectionOut.Y = intersectionPoint.Y; 150 | return collided; 151 | } 152 | 153 | public override void Update(float step_time) 154 | { 155 | lastPosition.X = position.X; 156 | lastPosition.Y = position.Y; 157 | //velocity.Y += (Constants.GRAVITY/2.0f) * step_time; 158 | position.X += velocity.X * step_time; 159 | position.Y += velocity.Y * step_time; 160 | 161 | 162 | 163 | this.Bounds.SetPosByTopLeft(position); 164 | this.hitCollisionRect = Bounds; 165 | 166 | var world = Scene.World; 167 | 168 | world.collideSAT(this, step_time, false, () => { 169 | velocity = new Vector2f(0.0f, 0.0f); 170 | this.Scene.QueueAction(() => 171 | { 172 | this.Scene.Effects.Place(position, "simple-explosion2"); 173 | }); 174 | 175 | this.kill(); 176 | }); 177 | 178 | /* 179 | if (this.checkCollisionWithWorld(owner.Scene.World, ref intersection)) 180 | { 181 | //this.alive = false; // if not set to false, bullets will be shown 182 | position.X = intersection.X; 183 | position.Y = intersection.Y; 184 | velocity = new Vector2f(0.0f, 0.0f); 185 | //cAssetManager.playSound("wallhit", 5); 186 | 187 | this.Scene.QueueAction(() => 188 | { 189 | this.Scene.Effects.Place(intersection, "simple-explosion2"); 190 | }); 191 | 192 | this.kill(); 193 | } 194 | */ 195 | 196 | if (!AppMath.Vec2IsZero(velocity)) 197 | { 198 | heading = AppMath.Vec2NormalizeReturn(velocity); 199 | //orientation = cAppMath.GetAngleOfVector(heading); 200 | //Side = Math->Vec2Perp(Heading); 201 | } 202 | } 203 | 204 | public void kill() 205 | { 206 | this.alive = false; 207 | } 208 | 209 | public bool Alive 210 | { 211 | get { return this.alive; } 212 | } 213 | 214 | public override bool isActive() 215 | { 216 | return this.alive; 217 | // && this.alpha > 1.0f; 218 | //&& cCollision.IsPointInsideBox(this.position, this.owner.Scene.World.WorldBounds); 219 | } 220 | 221 | public override void Render(RenderTarget destination) 222 | { 223 | //this.Bounds.SetPosByTopLeft(this.viewPosition); 224 | this.sprite.Position = this.viewPosition; 225 | Color c = this.sprite.Color; 226 | c.A = (byte)this.alpha; 227 | this.sprite.Color = c; 228 | 229 | //sprite.Rotation = (float)cAppMath.RadianToDegress(orientation); 230 | 231 | destination.Draw(this.sprite, this.blendMode); 232 | //cRenderFunctions.DrawLine(destination, this.viewPosition, this.viewPosition + this.oppositeDir, 2.0f, new Color(237, 247, 89, 255), BlendMode.Add); 233 | //cRenderFunctions.DrawRectangleShape(destination, this.Bounds, Color.Green, BlendMode.Add); //cAppMath.RadianToDegress(this.orientation) 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/cGameObject.cs: -------------------------------------------------------------------------------- 1 | using SFML.System; 2 | using SFML.Graphics; 3 | 4 | using platformerGame.Utilities; 5 | using platformerGame.Containers; 6 | using platformerGame.App; 7 | 8 | namespace platformerGame.GameObjects 9 | { 10 | class cGameObject : GridOccupant, IDrawable 11 | { 12 | protected int id; 13 | protected static int m_NextValidID; 14 | 15 | protected GameScene pscene; 16 | 17 | protected Vector2f position; 18 | protected Vector2f lastPosition; 19 | protected Vector2f viewPosition; // interpolációhoz 20 | 21 | protected Vector2f velocity; 22 | protected Vector2f acceleration; 23 | protected Vector2f force; 24 | 25 | protected Vector2f facing; // milyen irányba "néz" 26 | protected Vector2f heading; //milyen irányba halad 27 | 28 | protected Vector2f aabbOffset; 29 | protected double orientation; 30 | public float MaxSpeed { get; set; } 31 | public float SlowDown { get; set; } 32 | 33 | /// 34 | /// For Debug purposes. 35 | /// 36 | public bool Marked { get; set; } 37 | 38 | protected Vector2f viewSize; 39 | //protected cAABB boundingBox; 40 | 41 | 42 | protected float mass; 43 | 44 | protected bool movAble; 45 | 46 | protected AABB hitCollisionRect; 47 | protected float boundingRadius = 16.0f; // for separetion 48 | 49 | public cGameObject() : base() 50 | { 51 | pscene = null; 52 | position = new Vector2f(0.0f, 0.0f); 53 | lastPosition = new Vector2f(0.0f, 0.0f); 54 | viewPosition = new Vector2f(0.0f, 0.0f); 55 | 56 | velocity = new Vector2f(0.0f, 0.0f); 57 | acceleration = new Vector2f(0.0f, 0.0f); 58 | force = new Vector2f(0.0f, 0.0f); 59 | MaxSpeed = 0.0f; 60 | SlowDown = 1.0f; 61 | orientation = 0.0; 62 | mass = 1.0f; 63 | movAble = true; 64 | hitCollisionRect = new AABB(); 65 | 66 | this.Marked = false; 67 | id = GetNextValidID(); 68 | } 69 | 70 | public cGameObject(GameScene scene, Vector2f pos) : base() 71 | { 72 | pscene = scene; 73 | position = pos; 74 | lastPosition = pos; 75 | viewPosition = pos; 76 | 77 | this.GridPosition = new Vector2i(0, 0); 78 | 79 | velocity = new Vector2f(0.0f, 0.0f); 80 | acceleration = new Vector2f(0.0f, 0.0f); 81 | force = new Vector2f(0.0f, 0.0f); 82 | orientation = 0.0; 83 | mass = 1.0f; 84 | movAble = true; 85 | hitCollisionRect = new AABB(); 86 | this.Marked = false; 87 | id = GetNextValidID(); 88 | } 89 | 90 | public void Create() 91 | { 92 | this.GridPosition = EntityGrid.calcGridPos(this.Bounds.center); 93 | } 94 | 95 | protected static int GetNextValidID() 96 | { 97 | return m_NextValidID++; 98 | } 99 | 100 | public Vector2f ViewSize 101 | { 102 | get { return viewSize; } 103 | set { viewSize = value; } 104 | } 105 | 106 | public AABB HitCollisionRect 107 | { 108 | get { return hitCollisionRect; } 109 | set { hitCollisionRect = value; } 110 | } 111 | 112 | public int ID 113 | { 114 | get { return id; } 115 | } 116 | public GameScene Scene 117 | { 118 | get { return pscene; } 119 | } 120 | 121 | public Vector2f Position 122 | { 123 | get 124 | { 125 | return position; 126 | } 127 | 128 | set 129 | { 130 | position = value; 131 | } 132 | } 133 | 134 | public Vector2f LastPosition 135 | { 136 | get 137 | { 138 | return lastPosition; 139 | } 140 | 141 | set 142 | { 143 | lastPosition = value; 144 | } 145 | } 146 | 147 | public Vector2f ViewPosition 148 | { 149 | get 150 | { 151 | return viewPosition; 152 | } 153 | 154 | set 155 | { 156 | viewPosition = value; 157 | } 158 | } 159 | 160 | public Vector2f Velocity 161 | { 162 | get 163 | { 164 | return velocity; 165 | } 166 | 167 | set 168 | { 169 | velocity = value; 170 | } 171 | } 172 | 173 | public Vector2f Acceleration 174 | { 175 | get 176 | { 177 | return acceleration; 178 | } 179 | 180 | set 181 | { 182 | acceleration = value; 183 | } 184 | } 185 | 186 | public Vector2f Force 187 | { 188 | get 189 | { 190 | return force; 191 | } 192 | 193 | set 194 | { 195 | force = value; 196 | } 197 | } 198 | 199 | public Vector2f Heading 200 | { 201 | get 202 | { 203 | return heading; 204 | } 205 | 206 | set 207 | { 208 | heading = value; 209 | } 210 | } 211 | 212 | public Vector2f Facing 213 | { 214 | get 215 | { 216 | return facing; 217 | } 218 | 219 | set 220 | { 221 | facing = value; 222 | } 223 | } 224 | 225 | public Vector2f AabbOffset 226 | { 227 | get 228 | { 229 | return aabbOffset; 230 | } 231 | 232 | set 233 | { 234 | aabbOffset = value; 235 | } 236 | } 237 | 238 | public double Orientation 239 | { 240 | get 241 | { 242 | return orientation; 243 | } 244 | 245 | set 246 | { 247 | orientation = value; 248 | } 249 | } 250 | 251 | public float Mass 252 | { 253 | get { return this.mass; } 254 | set { this.mass = value; } 255 | } 256 | 257 | public bool MovAble 258 | { 259 | get { return this.movAble; } 260 | set { this.movAble = value; } 261 | } 262 | 263 | public bool Unmovable 264 | { 265 | get { return !this.movAble; } 266 | } 267 | 268 | public float BoundingRadius 269 | { 270 | get { return this.boundingRadius; } 271 | set { this.boundingRadius = value; } 272 | } 273 | 274 | public void AddForce(Vector2f impulse) 275 | { 276 | this.force += impulse; 277 | } 278 | 279 | public void CalculateViewPos(float alpha) 280 | { 281 | viewPosition = AppMath.Interpolate(position, lastPosition, alpha); 282 | } 283 | 284 | public virtual void Render(RenderTarget destination) 285 | { } 286 | 287 | public Vector2f GetCenterViewPos() 288 | { 289 | return viewPosition + Bounds.halfDims; 290 | } 291 | 292 | public Vector2f GetCenterPos() 293 | { 294 | return position + Bounds.halfDims; 295 | } 296 | 297 | public void MoveBy(Vector2f offset) 298 | { 299 | //this.lastPosition = position; 300 | this.position.X += offset.X; 301 | this.position.Y += offset.Y; 302 | } 303 | 304 | public void AddVelocity(Vector2f offset) 305 | { 306 | this.velocity.X += offset.X; 307 | this.velocity.Y += offset.Y; 308 | } 309 | 310 | public virtual void Kill(cGameObject by) 311 | { } 312 | 313 | 314 | public static cGameObject fromParticle(Particle p) 315 | { 316 | cGameObject go = new cGameObject(); 317 | go.Position = p.Pos; 318 | go.LastPosition = p.LastPos; 319 | go.Velocity = p.Vel; 320 | go.viewPosition = p.ViewPos; 321 | go.Bounds.SetDims(new Vector2f(2.0f, 2.0f)); 322 | go.Bounds.SetPosByCenter(p.Pos); 323 | go.mass = 1.0f; 324 | go.movAble = true; 325 | go.HitCollisionRect = go.Bounds.ShallowCopy(); 326 | return go; 327 | } 328 | 329 | public static cGameObject MakeWall(AABB box) 330 | { 331 | cGameObject go = new cGameObject(); 332 | go.Position = box.center; 333 | go.LastPosition = go.Position; 334 | go.Velocity = new Vector2f(0.0f, 0.0f); 335 | go.ViewPosition = go.Position; 336 | //box.SetDims(new Vector2f(Constants.TILE_SIZE, Constants.TILE_SIZE)); 337 | go.Bounds = box; 338 | go.HitCollisionRect = box; 339 | go.MovAble = false; // important! 340 | go.Mass = 0.0f; 341 | return go; 342 | } 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/cPickupAble.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.Graphics; 7 | using SFML.System; 8 | 9 | using platformerGame.Utilities; 10 | using platformerGame.GameObjects.PickupInfo; 11 | using platformerGame.Rendering; 12 | using platformerGame.App; 13 | 14 | namespace platformerGame.GameObjects 15 | { 16 | class cPickupAble : cGameObject 17 | { 18 | 19 | cPickupInfo pickup; 20 | 21 | cBaseRenderer renderer; 22 | 23 | bool pickedUp; 24 | bool pulling; 25 | 26 | const float EMIT_SPEED = 150.0f; 27 | const int MAX_PULL_DISTANCE = 80; 28 | const int PULL_FORCE = 10; 29 | 30 | public cPickupAble() : base() 31 | { } 32 | 33 | /// 34 | /// If pickup type is unknown (not specified), generate one by weights 35 | /// 36 | /// 37 | /// 38 | /// 39 | /// 40 | public cPickupAble(GameScene scene, Vector2f pos, Vector2f emit_direction, PickupType type = PickupType.UNKNOWN) : base(scene, pos) 41 | { 42 | pickup = type == PickupType.UNKNOWN ? PickupEffects.getWeighted() : PickupEffects.get(type); 43 | this.init(pos, emit_direction); 44 | } 45 | 46 | private void init(Vector2f pos, Vector2f emit_direction) 47 | { 48 | this.pickedUp = pulling = false; 49 | this.heading = emit_direction; 50 | 51 | this.renderer = pickup.Renderer.DeepCopy(); 52 | 53 | this.Bounds = new AABB(); 54 | this.Bounds.SetDims(this.pickup.HitRectSize); 55 | this.Bounds.SetPosByCenter(pos); 56 | this.HitCollisionRect = Bounds.ShallowCopy(); 57 | 58 | this.MaxSpeed = EMIT_SPEED * 2; //*2 59 | this.mass = 100.0f; 60 | 61 | this.velocity.X = this.heading.X * EMIT_SPEED; 62 | this.velocity.Y = this.heading.Y * EMIT_SPEED; 63 | orientation = AppMath.GetAngleOfVector(heading); 64 | } 65 | 66 | public override bool isActive() 67 | { 68 | return (false == pickedUp); 69 | } 70 | 71 | protected void checkCollisionWithWorld(float step_time) 72 | { 73 | cWorld world = Scene.World; 74 | 75 | if (false == pulling) 76 | { 77 | pscene.World.collideSAT(this, step_time); 78 | 79 | /* 80 | // check collisions with world 81 | List wallsPossibleColliding = world.getCollidableBlocks(Bounds); 82 | 83 | // we must check this, because we need to iterate through the possible 84 | // colliding tiles from other direction according to this condition 85 | if (velocity.X > 0.0f) 86 | { 87 | for (int i = 0; i < wallsPossibleColliding.Count; ++i) 88 | { 89 | cGameObject wallObject = cGameObject.MakeWall(wallsPossibleColliding[i]); 90 | if (cSatCollision.checkAndResolve(this, wallObject, step_time, true)) 91 | { 92 | return; 93 | } 94 | } 95 | } 96 | else 97 | { 98 | // we have to iterate from "end" to the "start" in order to have the last colliding block below us 99 | for (int i = wallsPossibleColliding.Count-1; i >= 0; --i) 100 | { 101 | cGameObject wallObject = cGameObject.MakeWall(wallsPossibleColliding[i]); 102 | if (cSatCollision.checkAndResolve(this, wallObject, step_time, true)) 103 | { 104 | return; 105 | } 106 | 107 | } 108 | } 109 | */ 110 | } 111 | } 112 | 113 | public override void Update(float step_time) 114 | { 115 | this.renderer.Update(step_time); 116 | 117 | cPlayer player = Scene.Player; 118 | if (this.pulling) 119 | { 120 | Vector2f predicted = AppMath.Vec2NormalizeReturn((player.Bounds.center + (player.Velocity * step_time)) - this.Bounds.center); 121 | // pull pickup 122 | //Vector2f toPlayer = cAppMath.Vec2NormalizeReturn(player.Bounds.center - this.Bounds.center); 123 | 124 | // G * ((m1*m2) / (d*d)) 125 | float f = PULL_FORCE * 150f; // * (100000.0f / ( d*d) ); 126 | this.AddForce(predicted * f); 127 | } 128 | /* 129 | else 130 | { 131 | this.pulling = false; 132 | } 133 | */ 134 | 135 | // applying some gravity 136 | force.Y += (false == pulling) ? (Constants.GRAVITY * 40.0f * step_time) : 0.0f; 137 | 138 | velocity.X += force.X * step_time; 139 | velocity.Y += force.Y * step_time; 140 | 141 | //velocity.X = Math.Abs(velocity.X) < 0.05f ? 0.0f : velocity.X; 142 | //velocity.Y = Math.Abs(velocity.Y) < 0.05f ? 0.0f : velocity.Y; 143 | 144 | double len = AppMath.Vec2Length(velocity); 145 | if (len < 0.1) 146 | { 147 | velocity = new Vector2f(0.0f, 0.0f); 148 | 149 | } 150 | 151 | AppMath.Vec2Truncate(ref velocity, MaxSpeed); 152 | 153 | // get more precise result calling it here (because of the updated velocity) 154 | // instead of calling at the beginning of this update method 155 | checkCollisionWithWorld(step_time); 156 | 157 | lastPosition = position; 158 | position.X += velocity.X * step_time; 159 | position.Y += velocity.Y * step_time; 160 | 161 | Bounds.SetPosByCenter(position); 162 | this.hitCollisionRect = Bounds; 163 | 164 | if (!AppMath.Vec2IsZero(velocity)) 165 | { 166 | heading = AppMath.Vec2NormalizeReturn(velocity); 167 | orientation = AppMath.GetAngleOfVector(heading); 168 | } 169 | 170 | force = new Vector2f(0.0f, 0.0f); 171 | } 172 | 173 | public override void Render(RenderTarget destination) 174 | { 175 | //sprite.Position = ViewPosition; 176 | //sprite.Rotation = (float)cAppMath.RadianToDegress(orientation); 177 | //destination.Draw(this.sprite, new RenderStates(BlendMode.Alpha)); 178 | 179 | this.renderer.Draw(destination, ViewPosition); 180 | 181 | /* 182 | RectangleShape rs = new RectangleShape(); 183 | rs.Size = collidingTile.dims; 184 | rs.Position = collidingTile.topLeft; 185 | rs.FillColor = new Color(255, 0, 0, 150); 186 | for(int i = 0; i< walls.Count; i++) 187 | { 188 | rs.Position = walls[i].topLeft; 189 | destination.Draw(rs, new RenderStates(BlendMode.Alpha)); 190 | } 191 | */ 192 | } 193 | 194 | public virtual void checkContactWithPlayer() 195 | { 196 | cPlayer player = Scene.Player; 197 | 198 | float d = (float)AppMath.Vec2Distance(player.Bounds.center, this.Bounds.center); 199 | 200 | if (!this.pulling) 201 | { 202 | this.pulling = d <= MAX_PULL_DISTANCE; 203 | } 204 | 205 | if (!pickedUp && cCollision.OverlapAABB(player.Bounds, this.HitCollisionRect)) 206 | { 207 | player.pickUp(pickup); 208 | pickedUp = true; 209 | } 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/cPlayer.cs: -------------------------------------------------------------------------------- 1 | using SFML.Graphics; 2 | using SFML.System; 3 | 4 | using platformerGame.Inventory.Weapons; 5 | using platformerGame.Utilities; 6 | using platformerGame.GameObjects.PickupInfo; 7 | using platformerGame.App; 8 | 9 | namespace platformerGame.GameObjects 10 | { 11 | class cPlayer : cCharacter 12 | { 13 | cWeapon weapon; 14 | Text healthText; 15 | 16 | cLight fireLight; 17 | 18 | public cPlayer(GameScene scene, Vector2f pos) : base(scene, pos) 19 | { 20 | fireLight = new cLight(); 21 | fireLight.Pos = this.Bounds.center; 22 | fireLight.Bleed = 10.0f; 23 | fireLight.Radius = 120.0f; 24 | fireLight.LinearizeFactor = 0.96f; 25 | fireLight.OriginalColor = new Color(136, 216, 176); 26 | fireLight.Color = new Color(136, 216, 176); 27 | fireLight.TurnOff(); 28 | this.Scene.LightMap.AddStaticLight(fireLight); 29 | 30 | 31 | p_followLight = new cLight(); 32 | p_followLight.Pos = this.Bounds.center; 33 | p_followLight.Radius = 160.0f; 34 | p_followLight.LinearizeFactor = 0.9f; 35 | p_followLight.OriginalColor = new Color(240, 219, 164); 36 | p_followLight.Color = new Color(240, 219, 164); 37 | // p_followLight.TurnOff(); 38 | this.Scene.LightMap.AddStaticLight(p_followLight); 39 | 40 | this.weapon = // new cMachineGun(this, Constants.DEFAULT_WEAPON_FIRING_FREQUENCY); 41 | new cShotgun(this, Constants.DEFAULT_WEAPON_FIRING_FREQUENCY); // 9 42 | 43 | this.health = 50; 44 | healthText = new Text("", Scene.Assets.GetFont("pf_tempesta_seven")); 45 | healthText.Position = new Vector2f(pscene.AppController.MainWindow.DefaultView.Size.X - 500, 30); 46 | healthText.CharacterSize = 28; // in pixels, not points! 47 | healthText.FillColor = Color.White; 48 | healthText.Style = Text.Styles.Bold; 49 | 50 | this.boundingRadius = 12.0f; 51 | } 52 | 53 | protected override void initSprites() 54 | { 55 | base.initSprites(); 56 | 57 | MyIntRect viewRect = Constants.CHAR_VIEW_RECT; 58 | 59 | spriteControl.AddAnimState(new cSpriteState(MotionType.STAND, HorizontalFacing.FACING_LEFT), 60 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 61 | Constants.CHAR_FRAME_WIDTH, 62 | Constants.CHAR_FRAME_HEIGHT, 63 | 0, 64 | 0, 65 | 0, 66 | 1, 67 | FRAME_TIME, 68 | viewRect); 69 | 70 | spriteControl.AddAnimState(new cSpriteState(MotionType.STAND, HorizontalFacing.FACING_RIGHT), 71 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 72 | Constants.CHAR_FRAME_WIDTH, 73 | Constants.CHAR_FRAME_HEIGHT, 74 | 0, 75 | 1, 76 | 0, 77 | 1, 78 | FRAME_TIME, 79 | viewRect); 80 | 81 | spriteControl.AddAnimState(new cSpriteState(MotionType.WALK, HorizontalFacing.FACING_LEFT), 82 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 83 | Constants.CHAR_FRAME_WIDTH, 84 | Constants.CHAR_FRAME_HEIGHT, 85 | 0, 86 | 0, 87 | 0, // 0 88 | 3, // 3 89 | 60, //FRAME_TIME, 90 | viewRect); 91 | 92 | spriteControl.AddAnimState(new cSpriteState(MotionType.WALK, HorizontalFacing.FACING_RIGHT), 93 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 94 | Constants.CHAR_FRAME_WIDTH, 95 | Constants.CHAR_FRAME_HEIGHT, 96 | 0, 97 | 1, 98 | 0, // 0 99 | 3, // 3 100 | 60, //FRAME_TIME, 101 | viewRect); 102 | 103 | spriteControl.AddAnimState(new cSpriteState(MotionType.JUMP, HorizontalFacing.FACING_LEFT), 104 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 105 | Constants.CHAR_FRAME_WIDTH, 106 | Constants.CHAR_FRAME_HEIGHT, 107 | 1, 108 | 0, 109 | 0, 110 | 1, 111 | FRAME_TIME, 112 | viewRect); 113 | 114 | spriteControl.AddAnimState(new cSpriteState(MotionType.JUMP, HorizontalFacing.FACING_RIGHT), 115 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 116 | Constants.CHAR_FRAME_WIDTH, 117 | Constants.CHAR_FRAME_HEIGHT, 118 | 1, 119 | 1, 120 | 0, 121 | 1, 122 | FRAME_TIME, 123 | viewRect); 124 | 125 | 126 | spriteControl.AddAnimState(new cSpriteState(MotionType.FALL, HorizontalFacing.FACING_LEFT), 127 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 128 | Constants.CHAR_FRAME_WIDTH, 129 | Constants.CHAR_FRAME_HEIGHT, 130 | 6, 131 | 0, 132 | 0, 133 | 1, 134 | FRAME_TIME, 135 | viewRect); 136 | 137 | spriteControl.AddAnimState(new cSpriteState(MotionType.FALL, HorizontalFacing.FACING_RIGHT), 138 | Scene.Assets.GetTexture(Constants.PLAYER_TEXTURE_NAME), 139 | Constants.CHAR_FRAME_WIDTH, 140 | Constants.CHAR_FRAME_HEIGHT, 141 | 6, 142 | 1, 143 | 0, 144 | 1, 145 | FRAME_TIME, 146 | viewRect); 147 | } 148 | protected override void init() 149 | { 150 | base.init(); 151 | walkSpeed = Constants.PLAYER_WALK_SPEED; 152 | maxWalkSpeed = Constants.PLAYER_MAX_WALK_SPEED; 153 | } 154 | 155 | public override void Update(float step_time) 156 | { 157 | base.Update(step_time); 158 | 159 | } 160 | 161 | public override void Render(RenderTarget destination) 162 | { 163 | 164 | //viewPosition = cAppMath.Interpolate(position, lastPosition, alpha); 165 | 166 | p_followLight.Pos = GetCenterViewPos(); 167 | fireLight.Pos = GetCenterViewPos(); 168 | 169 | spriteControl.Render(destination, viewPosition); 170 | base.Render(destination); 171 | /* 172 | shape.Position = viewPosition; // - (viewSize / 2.0f); 173 | destination.Draw(shape); 174 | */ 175 | healthText.DisplayedString = health.ToString(); 176 | destination.Draw(healthText); 177 | 178 | } 179 | 180 | public void pickUp(cPickupInfo pickup) 181 | { 182 | pickup.applyEffect(this); 183 | } 184 | 185 | 186 | public void ItemAction(Vector2f mouse_pos) 187 | { 188 | if (weapon.Fire(mouse_pos)) 189 | { 190 | //this.fireLight.TurnOn(); 191 | return; 192 | } 193 | //this.fireLight.TurnOff(); 194 | } 195 | 196 | public cWeapon CurrentWeapon 197 | { 198 | get { return weapon; } 199 | } 200 | 201 | ~cPlayer() 202 | { 203 | spriteControl.Clear(); 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /platformerGame/GameObjects/cTurret.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | using platformerGame.GameObjects.PickupInfo; 11 | using platformerGame.Rendering; 12 | using platformerGame.App; 13 | using platformerGame.Inventory.Weapons; 14 | 15 | namespace platformerGame.GameObjects 16 | { 17 | class cTurret : cGameObject 18 | { 19 | // Sprite sprite; 20 | const double SPOT_DISTANCE = 300.0; 21 | 22 | cMachineGun gun; 23 | Vector2f gunFacingDirection; 24 | 25 | RectangleShape shape; 26 | 27 | cLight light; 28 | 29 | public cTurret() : base() 30 | { 31 | 32 | } 33 | 34 | public cTurret(GameScene scene, Vector2f pos) : base(scene, pos) 35 | { 36 | this.Bounds.SetDims(new Vector2f(16, 16)); 37 | this.Bounds.SetPosByCenter(pos); 38 | 39 | gun = new cMachineGun(this, 6, "turret-bullet"); 40 | 41 | gunFacingDirection = new Vector2f(0.0f, -1.0f); 42 | 43 | shape = new RectangleShape(new Vector2f(Bounds.dims.X, Bounds.dims.Y)); 44 | shape.Origin = new Vector2f(Bounds.halfDims.X, Bounds.halfDims.Y); 45 | shape.FillColor = Color.Green; 46 | shape.Position = new Vector2f(pos.X, pos.Y); 47 | shape.Scale = new Vector2f(1.0f, 1.0f); 48 | 49 | light = new cLight(); 50 | light.Pos = this.Bounds.center; 51 | light.Radius = 100.0f; 52 | light.LinearizeFactor = 0.8f; 53 | light.Bleed = 8.0f; 54 | light.Color = new Color(20, 184, 87); 55 | this.Scene.LightMap.AddStaticLight(light); 56 | } 57 | 58 | public override void Update(float step_time) 59 | { 60 | double dist = AppMath.Vec2Distance(Scene.Player.Bounds.center, this.Bounds.center); 61 | if(dist <= SPOT_DISTANCE) 62 | { 63 | Vector2f toTarget = AppMath.Vec2NormalizeReturn((Scene.Player.Bounds.center + Scene.Player.Velocity) - this.Bounds.center); 64 | 65 | 66 | float ang = AppMath.GetAngleBetwenVecs(toTarget, gunFacingDirection); 67 | Quaternion q = Quaternion.CreateFromAxisAngle(new Vector3f(toTarget.X, toTarget.Y, 0.0f), ang); 68 | Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3f(gunFacingDirection.X, gunFacingDirection.Y, 0.0f), ang); 69 | q = Quaternion.Slerp(q, q2, ang); 70 | 71 | gunFacingDirection = new Vector2f(q.X, q.Y); // toTarget; 72 | gun.Fire(Scene.Player.Bounds.center /*+ Scene.Player.Velocity * step_time*/); 73 | } 74 | } 75 | 76 | public override void Kill(cGameObject by) 77 | { 78 | Scene.LightMap.remove(this.light); 79 | } 80 | 81 | public override bool isActive() 82 | { 83 | return base.isActive(); 84 | } 85 | 86 | public override void Render(RenderTarget destination) 87 | { 88 | destination.Draw(shape, new RenderStates(BlendMode.Add)); 89 | 90 | DrawingBase.DrawLine(destination, this.Bounds.center, this.Bounds.center + gunFacingDirection * 40.0f, Color.Yellow, BlendMode.Alpha); 91 | // DrawingBase.DrawRectangleShape(destination, this.Bounds, new Color(240,140,160), BlendMode.Alpha); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /platformerGame/GlobalClock.cs: -------------------------------------------------------------------------------- 1 | using platformerGame.Utilities; 2 | 3 | namespace platformerGame 4 | { 5 | public class GlobalClock 6 | { 7 | /*private static readonly GlobalClock instance = new GlobalClock();*/ 8 | 9 | private static AppTimer timer; 10 | /*private GlobalClock() { }*/ 11 | static GlobalClock() 12 | { 13 | timer = new AppTimer(); 14 | } 15 | /* 16 | public static GlobalClock Instance 17 | { 18 | get 19 | { 20 | return instance; 21 | } 22 | } 23 | */ 24 | public static void Start() 25 | { 26 | 27 | timer.Start(); 28 | } 29 | 30 | public static double GetCurrentTime() 31 | { 32 | return timer.GetCurrentTime(); 33 | } 34 | 35 | public static double GetTimeInMilliseconds() 36 | { 37 | return timer.GetCurrentTimeAsMilliseconds(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /platformerGame/IDrawable.cs: -------------------------------------------------------------------------------- 1 | using SFML.Graphics; 2 | 3 | namespace platformerGame 4 | { 5 | public interface IDrawable 6 | { 7 | //bool IsVisibleOnScreen(); 8 | void CalculateViewPos(float alpha); 9 | void Render(RenderTarget destination); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /platformerGame/IGame.cs: -------------------------------------------------------------------------------- 1 | using SFML.Graphics; 2 | using SFML.Window; 3 | 4 | namespace OverlordEngine 5 | { 6 | /* 7 | delegate void BeforeUpdateEvent(); 8 | delegate void UpdateEvent(float stepTime); 9 | delegate void PreRenderEvent(float alpha); 10 | delegate void RenderEvent(RenderTarget target); 11 | */ 12 | 13 | interface IGame 14 | { 15 | void Init(); 16 | void Destroy(); 17 | void OnSingleMouseClick(MouseButtonEventArgs e); 18 | void OnKeyPressed(KeyEventArgs e); 19 | void OnBeforeUpdate(); 20 | void OnUpdateFixed(float stepTime); 21 | void OnUpdateVariable(float stepTime = 1.0f); 22 | void OnPreRender(float alpha); 23 | void OnRender(RenderTarget target); 24 | } 25 | 26 | class PlatformerGame : IGame 27 | { 28 | public PlatformerGame() 29 | { 30 | } 31 | 32 | 33 | public void OnBeforeUpdate() 34 | { 35 | 36 | } 37 | 38 | public void OnPreRender(float alpha) 39 | { 40 | 41 | } 42 | 43 | public void OnRender(RenderTarget target) 44 | { 45 | 46 | } 47 | 48 | public void OnUpdateFixed(float stepTime) 49 | { 50 | 51 | } 52 | 53 | public void OnUpdateVariable(float stepTime = 1.0f) 54 | { 55 | 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /platformerGame/Inventory/Weapons/cMachineGun.cs: -------------------------------------------------------------------------------- 1 | using SFML.System; 2 | using platformerGame.GameObjects; 3 | using platformerGame.Utilities; 4 | using platformerGame.Particles; 5 | 6 | namespace platformerGame.Inventory.Weapons 7 | { 8 | class cMachineGun : cWeapon 9 | { 10 | 11 | public cMachineGun(cGameObject owner, int firing_frequency, string bullet_breed_id = "simple-bullet") 12 | : base(owner, firing_frequency, bullet_breed_id) 13 | { 14 | this.maxAmmo = 300; 15 | this.currentAmmo = maxAmmo; 16 | this.magazineCapacity = 30; 17 | this.timeToReload = 1.5f; 18 | this.spread = (float)AppMath.DegressToRadian(4); 19 | this.bulletsPerShot = 1; 20 | } 21 | 22 | public override bool Fire(Vector2f target) 23 | { 24 | if (this.isReadForNextShot()) 25 | { 26 | Vector2f dir = AppMath.Vec2NormalizeReturn(target - owner.Bounds.center); 27 | Vector2f toSpreadTarget = AppMath.GetRandomVecBySpread(dir, spread); 28 | 29 | 30 | this.Shot(toSpreadTarget); 31 | decreaseAmmo(); 32 | 33 | 34 | owner.Scene.Assets.PlaySound("cg1", 2); 35 | 36 | /* 37 | this.owner.Scene.QueueAction(() => 38 | { 39 | var e = this.owner.Scene.ParticleManager["explosions"] as cExplosionController; 40 | e.Line(new EmissionInfo(this.owner.Bounds.center, toSpreadTarget)); 41 | 42 | }); 43 | */ 44 | } 45 | 46 | return false; 47 | 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /platformerGame/Inventory/Weapons/cShotgun.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using SFML.System; 4 | 5 | using platformerGame.Utilities; 6 | using platformerGame.GameObjects; 7 | 8 | namespace platformerGame.Inventory.Weapons 9 | { 10 | class cShotgun : cWeapon 11 | { 12 | 13 | public cShotgun(cGameObject owner, int firing_frequency, string bullet_breed_id = "simple-bullet") 14 | : base(owner, firing_frequency, bullet_breed_id) 15 | { 16 | this.spread = (float)AppMath.DegressToRadian(3); 17 | this.bulletsPerShot = 4; 18 | } 19 | 20 | public override bool Fire(Vector2f target) 21 | { 22 | if (this.isReadForNextShot()) 23 | { 24 | Vector2f dir = AppMath.Vec2NormalizeReturn(target - owner.Bounds.center); 25 | float dirAngle = (float)AppMath.GetAngleOfVector(dir); 26 | float unitAngle = spread / bulletsPerShot; 27 | float tangle = dirAngle - ((bulletsPerShot / 2.0f) * unitAngle); 28 | for (int i = 0; i < bulletsPerShot; ++i) 29 | { 30 | tangle += i * unitAngle; 31 | //Vector2f toSpreadTarget = cAppMath.GetRandomVecBySpread(dir, spread); 32 | Vector2f toSpreadTarget = new Vector2f((float)Math.Cos(tangle), (float)Math.Sin(tangle)); 33 | 34 | this.Shot(toSpreadTarget); 35 | } 36 | 37 | owner.Scene.Assets.PlaySound("shotgun", 3); 38 | 39 | return true; 40 | 41 | } 42 | 43 | return false; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /platformerGame/Inventory/Weapons/cWeapon.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.System; 8 | using platformerGame.GameObjects; 9 | 10 | using platformerGame.Utilities; 11 | 12 | namespace platformerGame.Inventory.Weapons 13 | { 14 | // TODO: make inherited from Inventory.cItem 15 | abstract class cWeapon 16 | { 17 | protected cGameObject owner; 18 | protected cRegulator regulator; 19 | protected int firingFrequency; 20 | protected float spread; // in radian 21 | 22 | protected int currentAmmo; 23 | protected int maxAmmo; 24 | protected int magazineCapacity; 25 | protected int bulletsPerShot; 26 | protected float timeToReload; 27 | 28 | protected string bulletBreedID; 29 | 30 | public cWeapon(cGameObject owner, int firing_frequency, string bullet_breed_id) 31 | { 32 | this.owner = owner; 33 | this.firingFrequency = firing_frequency; 34 | this.regulator = new cRegulator(); 35 | this.regulator.resetByFrequency(firing_frequency); 36 | this.spread = (float)AppMath.DegressToRadian(2); 37 | this.bulletsPerShot = 1; 38 | this.bulletBreedID = bullet_breed_id; 39 | } 40 | 41 | protected bool isReadForNextShot() 42 | { 43 | return regulator.isReady(); 44 | } 45 | 46 | public abstract bool Fire(Vector2f target); 47 | /* 48 | { 49 | if(this.isReadForNextShot()) 50 | { 51 | Vector2f dir = AppMath.Vec2NormalizeReturn(target - owner.Bounds.center); 52 | Vector2f toSpreadTarget = AppMath.GetRandomVecBySpread(dir, spread); 53 | cBullet b = new cBullet(this.owner, owner.Bounds.center, toSpreadTarget); 54 | owner.Scene.EntityPool.AddBullet(b); 55 | } 56 | } 57 | */ 58 | 59 | // in every weapon, the same method used to add a bullet to the scene 60 | protected void Shot(Vector2f direction) 61 | { 62 | cBullet b = new cBullet(this.owner, BulletBreed.GetBreed(this.bulletBreedID), owner.Bounds.center, direction); 63 | owner.Scene.EntityPool.AddBullet(b); 64 | } 65 | 66 | protected void decreaseAmmo() 67 | { 68 | this.currentAmmo -= bulletsPerShot; 69 | } 70 | 71 | public int CurrentAmmo 72 | { 73 | get { return this.currentAmmo; } 74 | } 75 | 76 | public int MaxAmmo 77 | { 78 | get { return this.maxAmmo; } 79 | } 80 | 81 | public int FiringFrequency 82 | { 83 | get {return firingFrequency; } 84 | set { firingFrequency = value; } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /platformerGame/Inventory/cInventory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using platformerGame.GameObjects; 8 | 9 | namespace platformerGame.Inventory 10 | { 11 | class cInventory 12 | { 13 | Dictionary items; 14 | 15 | cGameObject owner; 16 | cItem currentItem = null; 17 | 18 | public cInventory() 19 | { 20 | this.items = new Dictionary(); 21 | } 22 | 23 | 24 | public void AddItem(string name, cItem item) 25 | { 26 | if(this.items.ContainsKey(name)) 27 | { 28 | this.items[name].HandleAlreadyHave(item); 29 | return; 30 | } 31 | 32 | this.items.Add(name, item); 33 | } 34 | 35 | public void Delete(string name) 36 | { 37 | this.items.Remove(name); 38 | } 39 | 40 | public bool Switch(string to_name) 41 | { 42 | if (this.items.ContainsKey(to_name)) 43 | { 44 | currentItem = items[to_name]; 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | 51 | public void Use() 52 | { 53 | currentItem.Use(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /platformerGame/Inventory/cItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Inventory 8 | { 9 | abstract class cItem 10 | { 11 | protected cInventory inventory; 12 | 13 | public cItem(cInventory invetory) 14 | { 15 | this.inventory = inventory; 16 | } 17 | 18 | public abstract void Use(); 19 | public abstract void HandleAlreadyHave(cItem item); 20 | 21 | public cInventory Inventory 22 | { 23 | get { return this.inventory; } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /platformerGame/Map/cTile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | 9 | namespace platformerGame.Map 10 | { 11 | enum TileType 12 | { 13 | EMPTY = 0, //Üres - járható 14 | WALL = 1, //Fal - nem járható 15 | ONEWAY_PLATFORM = 2, //"Leugrós" platform 16 | WATER = 3, //Víz 17 | SPIKE = 4 //Tüske 18 | } 19 | class cTile 20 | { 21 | /// 22 | /// Egyedi azonosító 23 | /// 24 | public int IdCode { get; set; } 25 | 26 | public int GlobalId { get; set; } 27 | /// 28 | /// Minden tile-nak van típusa 29 | /// 30 | public TileType Type { get; set; } 31 | 32 | public AABB PosOnTexture { get; set; } 33 | public bool PlayerCollidable { get; set; } 34 | 35 | public bool IsCheckedWater { get; set; } 36 | 37 | public cTile() 38 | { 39 | IdCode = 0; 40 | GlobalId = -1; 41 | Type = TileType.EMPTY; 42 | PlayerCollidable = false; 43 | PosOnTexture = new AABB(0, 0, 1, 1); 44 | IsCheckedWater = false; 45 | } 46 | public cTile(int id_code, TileType type) 47 | { 48 | this.IdCode = id_code; 49 | this.Type = type; 50 | GlobalId = -1; 51 | PlayerCollidable = false; 52 | PosOnTexture = new AABB(0, 0, 1, 1); 53 | IsCheckedWater = false; 54 | 55 | } 56 | 57 | public cTile(cTile other) 58 | { 59 | this.IdCode = other.IdCode; 60 | this.Type = other.Type; 61 | } 62 | 63 | public cTile ShallowCopy() 64 | { 65 | return (cTile)this.MemberwiseClone(); 66 | } 67 | public bool IsWalkAble() 68 | { 69 | return (Type != TileType.WALL); 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /platformerGame/Map/cTileLayer.cs: -------------------------------------------------------------------------------- 1 | using SFML.Graphics; 2 | using SFML.System; 3 | using System.Collections.Generic; 4 | 5 | namespace platformerGame.Map 6 | { 7 | class cTileLayer 8 | { 9 | // TileLayerType 10 | int typeID; 11 | 12 | VertexArray vertices; 13 | 14 | RenderStates renderStates; 15 | 16 | public cTileLayer(int type_id, Texture tile_set) 17 | { 18 | this.typeID = type_id; 19 | this.vertices = new VertexArray(PrimitiveType.Quads); 20 | this.renderStates = new RenderStates(BlendMode.Alpha); 21 | this.renderStates.Texture = tile_set; 22 | } 23 | 24 | public void ClearVertexArray() 25 | { 26 | this.vertices.Clear(); 27 | } 28 | 29 | public void AddTileVertices(AABB tile_region, AABB pos_in_tileset) 30 | { 31 | vertices.Append(new Vertex(new Vector2f(tile_region.topLeft.X, tile_region.topLeft.Y), Color.White, new Vector2f(pos_in_tileset.topLeft.X, pos_in_tileset.topLeft.Y))); 32 | vertices.Append(new Vertex(new Vector2f(tile_region.getTopRight().X, tile_region.getTopRight().Y), Color.White, new Vector2f(pos_in_tileset.getTopRight().X, pos_in_tileset.getTopRight().Y))); 33 | vertices.Append(new Vertex(new Vector2f(tile_region.rightBottom.X, tile_region.rightBottom.Y), Color.White, new Vector2f(pos_in_tileset.rightBottom.X, pos_in_tileset.rightBottom.Y))); 34 | vertices.Append(new Vertex(new Vector2f(tile_region.getLeftBottom().X, tile_region.getLeftBottom().Y), Color.White, new Vector2f(pos_in_tileset.getLeftBottom().X, pos_in_tileset.getLeftBottom().Y))); 35 | } 36 | 37 | public void Draw(RenderTarget destination) 38 | { 39 | destination.Draw(vertices, renderStates); 40 | } 41 | 42 | public int TypeID 43 | { 44 | get { return typeID; } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /platformerGame/Map/cTileMapRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | 11 | namespace platformerGame.Map 12 | { 13 | class cTileMapRenderer 14 | { 15 | cWorld world; 16 | 17 | List drawTileLayers; 18 | 19 | AABB drawTileBounds; 20 | 21 | Texture tileSetTexture; 22 | 23 | public cTileMapRenderer(cWorld world) 24 | { 25 | this.world = world; 26 | this.drawTileLayers = new List(); 27 | 28 | this.tileSetTexture = world.CurrentLevel.TilesetTexture; 29 | 30 | drawTileBounds = new AABB(); 31 | 32 | this.setupLayers(); 33 | 34 | // textureOfTiles = new RenderTexture((uint)m_WorldBounds.dims.X, (uint)m_WorldBounds.dims.Y); //(windowSize.X, windowSize.Y); 35 | // textureOfTiles.SetActive(true); 36 | 37 | } 38 | 39 | private void setupLayers() 40 | { 41 | drawTileLayers.Add(new cTileLayer(TileLayerTypes.BACKGROUND_1, tileSetTexture)); 42 | drawTileLayers.Add(new cTileLayer(TileLayerTypes.BACKGROUND_2, tileSetTexture)); 43 | drawTileLayers.Add(new cTileLayer(TileLayerTypes.WALLS, tileSetTexture)); 44 | } 45 | 46 | public void ClearTileLayers() 47 | { 48 | foreach (var layer in drawTileLayers) 49 | { 50 | layer.ClearVertexArray(); 51 | } 52 | } 53 | 54 | /// 55 | /// Filters the visible tiles and build the vertex arrays of each layer 56 | /// 57 | private void filterDrawableTiles() 58 | { 59 | int startTileX = (int)drawTileBounds.topLeft.X; 60 | int startTileY = (int)drawTileBounds.topLeft.Y; 61 | int endTileX = (int)drawTileBounds.rightBottom.X; 62 | int endTileY = (int)drawTileBounds.rightBottom.Y; 63 | 64 | // important to call !! 65 | this.ClearTileLayers(); 66 | 67 | 68 | Vector2f drawPos = new Vector2f(); 69 | 70 | const int spaceOffset = 0; 71 | 72 | for (int y = startTileY; y < endTileY; y++) 73 | { 74 | for (int x = startTileX; x < endTileX; x++) 75 | { 76 | for (int layer = 0; layer < drawTileLayers.Count; layer++) 77 | { 78 | cTile tempTile = world.CurrentLevel.GetTileAtXY(x, y, drawTileLayers[layer].TypeID); 79 | 80 | if (tempTile.Type != TileType.EMPTY) 81 | { 82 | // tilesToDraw.Add(new DrawTile(x, y, tempTile.PosOnTexture)); 83 | 84 | drawPos.X = (world.WorldBounds.topLeft.X + x * Constants.TILE_SIZE) + spaceOffset; 85 | drawPos.Y = (world.WorldBounds.topLeft.Y + y * Constants.TILE_SIZE) + spaceOffset; 86 | 87 | AABB tileBounds = world.getAABBFromWorldPos(drawPos); 88 | 89 | drawTileLayers[layer].AddTileVertices(tileBounds, tempTile.PosOnTexture); 90 | } 91 | } 92 | } 93 | } 94 | 95 | } 96 | 97 | public void RecalculateDrawBounds(AABB viewRect) 98 | { 99 | drawTileBounds = viewRect.ShallowCopy(); 100 | 101 | drawTileBounds.topLeft.X = (float)Math.Floor((drawTileBounds.topLeft.X / Constants.TILE_SIZE) - 1); 102 | drawTileBounds.topLeft.Y = (float)Math.Floor((drawTileBounds.topLeft.Y / Constants.TILE_SIZE) - 1); 103 | 104 | drawTileBounds.rightBottom.X = (float)Math.Ceiling((drawTileBounds.rightBottom.X / Constants.TILE_SIZE) + 1); 105 | drawTileBounds.rightBottom.Y = (float)Math.Ceiling((drawTileBounds.rightBottom.Y / Constants.TILE_SIZE) + 1); 106 | 107 | // TODO comment 108 | drawTileBounds.topLeft.X = Math.Max(drawTileBounds.topLeft.X, 0.0f); 109 | drawTileBounds.topLeft.Y = Math.Max(drawTileBounds.topLeft.Y, 0.0f); 110 | drawTileBounds.rightBottom.X = Math.Min(drawTileBounds.rightBottom.X, this.world.CurrentLevel.Width); 111 | drawTileBounds.rightBottom.Y = Math.Min(drawTileBounds.rightBottom.Y, this.world.CurrentLevel.Height); 112 | 113 | filterDrawableTiles(); 114 | 115 | } 116 | public void Render(RenderTarget destination, AABB view_rect = null) 117 | { 118 | foreach (var layer in drawTileLayers) 119 | { 120 | layer.Draw(destination); 121 | } 122 | 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /platformerGame/MapCollider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame 8 | { 9 | class MapCollider 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /platformerGame/Particles/EmissionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.System; 8 | 9 | namespace platformerGame.Particles 10 | { 11 | class EmissionInfo 12 | { 13 | Particle particleRef; 14 | Vector2f startPosition; 15 | Vector2f emitDirection; 16 | float speed; // should be normalized 17 | 18 | public Particle Particle 19 | { 20 | get { return particleRef; } 21 | set { particleRef = value; } 22 | } 23 | 24 | public Vector2f StartPosition 25 | { 26 | get { return startPosition; } 27 | set { startPosition = value; } 28 | } 29 | 30 | public Vector2f EmitDirection 31 | { 32 | get { return emitDirection; } 33 | set { emitDirection = value; } 34 | } 35 | 36 | public float Speed 37 | { 38 | get { return this.speed; } 39 | } 40 | 41 | public EmissionInfo(Vector2f start_position) 42 | { 43 | this.particleRef = null; 44 | this.startPosition = start_position; 45 | this.emitDirection = new Vector2f(0.0f, 0.0f); 46 | this.speed = 0.0f; 47 | } 48 | 49 | public EmissionInfo(Vector2f start_position, Vector2f emit_direction, float speed = 0.0f) 50 | { 51 | this.particleRef = null; 52 | this.startPosition = start_position; 53 | this.emitDirection = emit_direction; 54 | this.speed = speed; 55 | } 56 | 57 | public EmissionInfo(Particle particle, Vector2f start_position) 58 | { 59 | this.particleRef = particle; 60 | this.startPosition = start_position; 61 | this.emitDirection = new Vector2f(0.0f, 0.0f); 62 | this.speed = 0.0f; 63 | } 64 | 65 | public EmissionInfo(Particle particle, Vector2f start_position, Vector2f emit_direction, float speed = 0.0f) 66 | { 67 | this.particleRef = particle; 68 | this.startPosition = start_position; 69 | this.emitDirection = emit_direction; 70 | this.speed = speed; 71 | } 72 | 73 | public bool hasSpeed() 74 | { 75 | return speed > 0.0f; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /platformerGame/Particles/IParticleContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Particles 8 | { 9 | interface IParticleContainer 10 | { 11 | Particle getNew(); 12 | Particle get(uint index); 13 | void activate(uint index); 14 | void deactivate(uint index); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /platformerGame/Particles/Particle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.System; 8 | using SFML.Graphics; 9 | 10 | namespace platformerGame 11 | { 12 | class Particle 13 | { 14 | public Vector2f Pos; 15 | public Vector2f LastPos; 16 | public Vector2f ViewPos; 17 | public Vector2f StartPos; 18 | 19 | public Vector2f Dims; //width, height 20 | public Vector2f Vel; // velocity 21 | public Vector2f Heading; 22 | 23 | public Color Color; 24 | public float SlowDown; 25 | public float MaxSpeed; 26 | public float ScaleSpeed; 27 | public float Opacity; 28 | public float Fade; 29 | public float Life; 30 | public float Scale; 31 | 32 | public float Rotation; // in radian 33 | 34 | public bool Intersects; 35 | 36 | /* 37 | * UpdateController updater; 38 | * 39 | */ 40 | 41 | public Particle() 42 | { 43 | Pos = new Vector2f(0.0f, 0.0f); 44 | LastPos = new Vector2f(0.0f, 0.0f); 45 | ViewPos = new Vector2f(0.0f, 0.0f); 46 | StartPos = new Vector2f(0.0f, 0.0f); 47 | Dims = new Vector2f(2.0f, 2.0f); // 2x2 square 48 | Vel = new Vector2f(0.0f, 0.0f); 49 | Heading = new Vector2f(0.0f, 0.0f); 50 | Color = new Color(255, 255, 255, 255); 51 | SlowDown = 0.789f; 52 | MaxSpeed = 200.0f; 53 | ScaleSpeed = 0.0f; 54 | Opacity = 255.0f; 55 | Fade = 255.0f; 56 | Life = 1.0f; 57 | Rotation = 0.0f; 58 | Scale = 1.0f; 59 | Intersects = false; 60 | } 61 | 62 | public AABB getBoundingBox() 63 | { 64 | AABB b = new AABB(); 65 | b.SetDims(Dims); 66 | b.SetPosByCenter(Pos); 67 | return b; 68 | } 69 | 70 | public Particle(Particle p) 71 | { 72 | this.Pos = p.Pos; 73 | this.LastPos = p.LastPos; 74 | this.ViewPos = p.ViewPos; 75 | this.StartPos = p.StartPos; 76 | this.Dims = p.Dims; 77 | this.Vel = p.Vel; 78 | this.Heading = p.Heading; 79 | this.Color = new Color(p.Color); 80 | this.SlowDown = p.SlowDown; 81 | this.MaxSpeed = p.MaxSpeed; 82 | this.ScaleSpeed = p.ScaleSpeed; 83 | this.Opacity = p.Opacity; 84 | this.Fade = p.Fade; 85 | this.Life = p.Life; 86 | this.Rotation = p.Rotation; 87 | this.Scale = p.Scale; 88 | this.Intersects = p.Intersects; 89 | } 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /platformerGame/Particles/cBaseParticleController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | 8 | using SFML.System; 9 | using SFML.Graphics; 10 | 11 | namespace platformerGame.Particles 12 | { 13 | abstract class cBaseParticleController 14 | { 15 | protected cParticleManager particleManager; 16 | protected cParticlePool pool; 17 | protected VertexArray vertices; 18 | protected RenderStates renderStates; 19 | 20 | public cBaseParticleController(cParticleManager manager, int max_particles = 300) 21 | { 22 | this.particleManager = manager; 23 | this.pool = new cParticlePool(max_particles); // new ParticlePoolList() 24 | this.vertices = new VertexArray(PrimitiveType.Quads); 25 | this.renderStates = new RenderStates(BlendMode.Add); 26 | } 27 | 28 | protected void loopAddition(EmissionInfo emission, uint num_particles) 29 | { 30 | uint i = 0; 31 | while ((emission.Particle = pool.getNew()) != null && i < num_particles) 32 | { 33 | initParticle(emission); 34 | ++i; 35 | } 36 | } 37 | 38 | public int NumActive 39 | { 40 | get { return (int)pool.CountActive; } 41 | } 42 | 43 | protected abstract void initParticle(EmissionInfo emission); 44 | 45 | public abstract void Update(float step_time); 46 | 47 | public abstract void BuildVertexBuffer(float alpha); 48 | 49 | public abstract void Render(RenderTarget destination, float alpha); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /platformerGame/Particles/cFireworksController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Diagnostics; 7 | 8 | using SFML.System; 9 | using SFML.Graphics; 10 | 11 | using platformerGame.Utilities; 12 | 13 | namespace platformerGame.Particles 14 | { 15 | class cFireworksController : cBaseParticleController 16 | { 17 | double minScale = 0.3; 18 | double maxScale = 0.6; 19 | 20 | public cFireworksController(cParticleManager manager, int max_particles = 300) : base(manager, max_particles) 21 | { 22 | this.renderStates.Texture = manager.FireworksTexture; 23 | } 24 | 25 | 26 | protected override void initParticle(EmissionInfo emission) 27 | { 28 | Particle particle = emission.Particle; 29 | 30 | particle.Pos = emission.StartPosition; 31 | particle.LastPos = particle.Pos; 32 | particle.ViewPos = particle.Pos; 33 | particle.MaxSpeed = AppMath.GetRandomNumber(600, 800); //200,400 | 700, 900 | (400, 600); //3, 8//Math->GetRandomNumber(510, 800); // 2000.0f 34 | 35 | //------------------------------------------------------------------------------------------------ 36 | float angle = (float)AppMath.DegressToRadian(AppMath.GetRandomNumber(0, 360));//sDivisions * m_Angles; 37 | 38 | particle.Vel = new Vector2f((float)Math.Cos(angle) * particle.MaxSpeed, (float)Math.Sin(angle) * particle.MaxSpeed); 39 | //------------------------------------------------------------------------------------------------ 40 | //------------------------------------------------------------------------------------------------ 41 | 42 | //particle.m_Vel = sf::Vector2f(Math->GetRandomClamped() * particle.m_MaxSpeed, Math->GetRandomClamped() *particle.m_MaxSpeed); 43 | particle.SlowDown = 0.98f; //0.92f; 44 | //particle.m_SlowDown = (float)Math->GetRandomDoubleInRange(0.55, 0.7); //0.6f; 45 | //phs->AddForce( sf::Vector2f(Math->GetRandomClamped() * phs->MaxSpeed, Math->GetRandomClamped() * phs->MaxSpeed) ); 46 | 47 | Vector2u uSize = this.renderStates.Texture.Size; 48 | 49 | particle.Scale = (float)AppMath.GetRandomDoubleInRange(this.minScale, this.maxScale); 50 | 51 | particle.Dims = new Vector2f(uSize.X * particle.Scale, uSize.Y * particle.Scale); 52 | 53 | particle.ScaleSpeed = -AppMath.GetRandomNumber(10, 50); 54 | particle.Color = Utils.GetRandomRedColor(); 55 | particle.Opacity = 255.0f; 56 | particle.Life = 1.0f; 57 | particle.Fade = 60; //Math->GetRandomNumber(100, 240); 58 | 59 | particle.Intersects = false; 60 | } 61 | 62 | public void LittleExplosion(EmissionInfo emission) 63 | { 64 | minScale = 0.2; 65 | maxScale = 0.4; 66 | loopAddition(emission, 3); 67 | } 68 | 69 | public void NormalExplosion(EmissionInfo emission) 70 | { 71 | minScale = 0.5; 72 | maxScale = 0.8; 73 | loopAddition(emission, 20); 74 | } 75 | 76 | public override void Update(float step_time) 77 | { 78 | cWorld world = particleManager.Scene.World; 79 | 80 | for (int i = 0; i < pool.CountActive; ++i) 81 | { 82 | Particle p = pool.get(i); 83 | 84 | if (!p.Intersects) 85 | { 86 | 87 | /* 88 | p.Dims.Y += p.ScaleSpeed * step_time; //+= 89 | p.Dims.y += p.ScaleSpeed * step_time; //+= 90 | */ 91 | AppMath.Vec2Truncate(ref p.Vel, p.MaxSpeed * 1.5f); 92 | 93 | 94 | p.Vel.Y += (Constants.GRAVITY * 40.0f * (step_time * step_time)); 95 | 96 | p.Vel.X *= p.SlowDown; 97 | p.Vel.Y *= p.SlowDown; 98 | 99 | //p.Heading = cAppMath.Vec2NormalizeReturn(p.Vel); 100 | p.LastPos = p.Pos; 101 | p.Pos.X += p.Vel.X * step_time; 102 | p.Pos.Y += p.Vel.Y * step_time; 103 | 104 | 105 | 106 | if (!AppMath.Vec2IsZero(p.Vel)) 107 | { 108 | p.Heading = AppMath.Vec2NormalizeReturn(p.Vel); 109 | p.Rotation = (float)AppMath.GetAngleOfVector(p.Heading); 110 | } 111 | 112 | world.collideParticleRayTrace(p, step_time); 113 | 114 | 115 | } 116 | 117 | p.Opacity -= p.Fade * step_time; 118 | 119 | if (p.Opacity <= 0.0f) 120 | { 121 | p.Opacity = 0.0f; 122 | 123 | pool.deactivate(i); 124 | 125 | } 126 | 127 | p.Color.A = (byte)p.Opacity; 128 | } 129 | } 130 | 131 | public override void BuildVertexBuffer(float alpha) 132 | { 133 | uint multiplier = 4; 134 | uint vNum = ((uint)pool.CountActive * multiplier) + 1; 135 | 136 | //vertices.Clear(); 137 | vertices.Resize(vNum); 138 | 139 | float division = 2.0f; 140 | 141 | Vector2u uSize = this.renderStates.Texture.Size; 142 | float tSizeX = uSize.X; 143 | float tSizeY = uSize.Y; 144 | 145 | Vector2f newDims = new Vector2f(); 146 | 147 | for (int i = 0; i < pool.CountActive; ++i) 148 | { 149 | Particle p = pool.get(i); 150 | 151 | newDims.X = p.Dims.X / division; 152 | newDims.Y = p.Dims.Y / division; 153 | 154 | p.ViewPos = AppMath.Interpolate(p.Pos, p.LastPos, alpha); 155 | 156 | uint vertexIndex = (uint)i * multiplier; 157 | 158 | Vector2f v0Pos = new Vector2f(p.ViewPos.X - newDims.X, 159 | p.ViewPos.Y - newDims.Y); 160 | 161 | Vector2f v1Pos = new Vector2f(p.ViewPos.X + newDims.X, 162 | p.ViewPos.Y - newDims.Y); 163 | 164 | Vector2f v2Pos = new Vector2f(p.ViewPos.X + newDims.X, 165 | p.ViewPos.Y + newDims.Y); 166 | 167 | Vector2f v3Pos = new Vector2f(p.ViewPos.X - newDims.X, 168 | p.ViewPos.Y + newDims.Y); 169 | 170 | 171 | // if want rotation included: 172 | Transform rot = Transform.Identity; 173 | rot.Rotate((float)AppMath.RadianToDegress(p.Rotation), p.ViewPos); 174 | 175 | v0Pos = rot.TransformPoint(v0Pos); 176 | v1Pos = rot.TransformPoint(v1Pos); 177 | v2Pos = rot.TransformPoint(v2Pos); 178 | v3Pos = rot.TransformPoint(v3Pos); 179 | // END of rotation code 180 | 181 | // Top-left 182 | Vertex v0 = new Vertex( 183 | v0Pos, 184 | p.Color, 185 | new Vector2f(0.0f, 0.0f) 186 | ); 187 | 188 | // Top-right 189 | Vertex v1 = new Vertex( 190 | v1Pos, 191 | p.Color, 192 | new Vector2f(tSizeX, 0.0f) 193 | ); 194 | 195 | // Bottom-right 196 | Vertex v2 = new Vertex( 197 | v2Pos, 198 | p.Color, 199 | new Vector2f(tSizeX, tSizeY) 200 | ); 201 | 202 | //Bottom-left 203 | Vertex v3 = new Vertex( 204 | v3Pos, 205 | p.Color, 206 | new Vector2f(0.0f, tSizeY) 207 | ); 208 | 209 | vertices[vertexIndex + 0] = v0; 210 | vertices[vertexIndex + 1] = v1; 211 | vertices[vertexIndex + 2] = v2; 212 | vertices[vertexIndex + 3] = v3; 213 | } 214 | } 215 | 216 | public override void Render(RenderTarget destination, float alpha) 217 | { 218 | destination.Draw(vertices, renderStates); 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /platformerGame/Particles/cParticleManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.App; 10 | 11 | namespace platformerGame.Particles 12 | { 13 | 14 | /// 15 | /// This class attempts to handle particle effects effictively by using different controllers, which are 16 | /// operate on the particles stored in the particle pool. 17 | /// 18 | class cParticleManager 19 | { 20 | GameScene sceneRef; 21 | 22 | readonly Texture explosionTexture; 23 | readonly Texture fireworksTexture; 24 | readonly Texture smokeTexture; 25 | 26 | Dictionary systems; 27 | 28 | Text label; 29 | 30 | public cParticleManager(GameScene scene) 31 | { 32 | this.sceneRef = scene; 33 | this.systems = new Dictionary(); 34 | 35 | // must be called before controller additions 36 | explosionTexture = scene.Assets.GetTexture("simple_particle"); //simple_particle 37 | fireworksTexture = scene.Assets.GetTexture("bullet3"); 38 | smokeTexture = scene.Assets.GetTexture("smoke_particle"); 39 | 40 | this.systems.Add("explosions", new cExplosionController(this)); 41 | this.systems.Add("fireworks", new cFireworksController(this)); 42 | this.systems.Add("sprays", new cSprayController(this)); 43 | 44 | label = new Text(); 45 | label.Position = new Vector2f(20, 45); 46 | 47 | label.Font = scene.Assets.GetFont("BGOTHL"); 48 | label.CharacterSize = 24; 49 | label.FillColor = Color.White; 50 | label.Style = Text.Styles.Bold; 51 | 52 | } 53 | 54 | public void Update(float step_time) 55 | { 56 | foreach (var item in systems) 57 | { 58 | cBaseParticleController c = item.Value; 59 | c.Update(step_time); 60 | } 61 | } 62 | 63 | public void PreRender(float alpha) 64 | { 65 | // if we want calculate viewPos before all renderings are started... 66 | foreach (var item in systems) 67 | { 68 | cBaseParticleController c = item.Value; 69 | c.BuildVertexBuffer(alpha); 70 | } 71 | } 72 | 73 | public void Render(RenderTarget destination, float alpha) 74 | { 75 | //label.DisplayedString = "Active explosion particles: " + explosions.NumActive.ToString(); 76 | //destination.Draw(label); 77 | foreach (var item in systems) 78 | { 79 | cBaseParticleController c = item.Value; 80 | c.Render(destination, alpha); 81 | } 82 | } 83 | 84 | public Texture ExplosionTexture 85 | { 86 | get { return explosionTexture; } 87 | } 88 | 89 | public Texture FireworksTexture 90 | { 91 | get { return fireworksTexture; } 92 | } 93 | 94 | public Texture SmokeTexture 95 | { 96 | get { return smokeTexture; } 97 | } 98 | 99 | public GameScene Scene 100 | { 101 | get { return sceneRef; } 102 | } 103 | 104 | public cBaseParticleController this[string key] 105 | { 106 | get 107 | { 108 | cBaseParticleController s; 109 | return this.systems.TryGetValue(key, out s) ? s : null; 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /platformerGame/Particles/cParticlePool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.System; 8 | using SFML.Graphics; 9 | 10 | namespace platformerGame.Particles 11 | { 12 | /// 13 | /// Simple class storing the particles. 14 | /// 15 | class cParticlePool 16 | { 17 | int capacity; 18 | Particle[] particles; 19 | int countActive; 20 | 21 | public cParticlePool() 22 | { 23 | capacity = 10; 24 | initParticles(); 25 | countActive = 0; 26 | } 27 | 28 | public cParticlePool(int capacity) 29 | { 30 | this.capacity = capacity; 31 | initParticles(); 32 | countActive = 0; 33 | } 34 | 35 | private void initParticles() 36 | { 37 | particles = new Particle[capacity]; 38 | for(int i = 0; i < particles.Length; i++) 39 | { 40 | particles[i] = new Particle(); 41 | } 42 | } 43 | 44 | void swap(int indexA, int indexB) 45 | { 46 | Particle temp = particles[indexA]; 47 | particles[indexA] = particles[indexB]; 48 | particles[indexB] = temp; 49 | } 50 | 51 | void swapR(ref Particle A, ref Particle B) 52 | { 53 | Particle C = A; 54 | A = B; 55 | B = C; 56 | } 57 | 58 | /// 59 | /// Gets a new particle. 60 | /// 61 | /// A tuple: Item1 is the index of the particle, Item2 is the particle. 62 | public Particle getNew() 63 | { 64 | int current = countActive++; 65 | 66 | if (countActive > capacity) 67 | { 68 | countActive = capacity; 69 | return null; 70 | } 71 | 72 | return particles[current]; 73 | 74 | } 75 | 76 | private bool checkIndex(int index) 77 | { 78 | return index >= 0 && index < particles.Length; 79 | } 80 | 81 | 82 | public Particle get(int index) 83 | { 84 | //return checkIndex(index) ? particles[index] : null; 85 | return particles[index]; 86 | } 87 | 88 | public void activate(int index) 89 | { 90 | swap(index, countActive); 91 | countActive++; 92 | } 93 | 94 | public void deactivate(int index) 95 | { 96 | //if (checkIndex(index)) 97 | { 98 | swap(index, countActive-1); 99 | countActive--; 100 | } 101 | } 102 | 103 | public int CountActive 104 | { 105 | get { return countActive; } 106 | } 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /platformerGame/Particles/cParticlePoolList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Particles 8 | { 9 | class cParticlePoolList 10 | { 11 | List particles; 12 | int countActive; 13 | 14 | public cParticlePoolList(int max_particles) 15 | { 16 | particles = new List(max_particles); 17 | countActive = 0; 18 | } 19 | 20 | public Particle getNew() 21 | { 22 | Particle p = new Particle(); 23 | particles.Add(p); 24 | countActive++; 25 | return p; 26 | } 27 | 28 | private bool checkIndex(int index) 29 | { 30 | return index >= 0 && index < particles.Count; 31 | } 32 | 33 | public Particle get(int index) 34 | { 35 | return particles[index]; 36 | } 37 | 38 | public void deactivate(int index) 39 | { 40 | particles.RemoveAt(index); 41 | countActive--; 42 | } 43 | 44 | public int CountActive 45 | { 46 | get { return countActive; } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /platformerGame/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | 8 | using platformerGame.App; 9 | 10 | namespace platformerGame 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | SfmlApp gameApp = null; 17 | 18 | try 19 | { 20 | gameApp = new SfmlApp(); 21 | gameApp.Run(); 22 | } 23 | catch (Exception ex) 24 | { 25 | StreamWriter sw = new StreamWriter("ErrorLog_" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt"); 26 | sw.WriteLine("Error created at " + DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss tt")); //yyyy/MM/dd HH:mm:ss: 27 | sw.WriteLine(ex.Message); 28 | sw.WriteLine(ex.Data.ToString()); 29 | 30 | sw.WriteLine(ex.StackTrace); 31 | sw.Close(); 32 | 33 | System.Diagnostics.Debug.WriteLine(ex.Message); 34 | System.Diagnostics.Debug.WriteLine(ex.Data.ToString()); 35 | System.Diagnostics.Debug.WriteLine(ex.StackTrace); 36 | while (true) { } 37 | 38 | } 39 | 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /platformerGame/Regulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame 8 | { 9 | class cRegulator 10 | { 11 | double freq; 12 | double periodTime; //in seconds 13 | 14 | //in milliseconds 15 | double currentTime = 0.0; 16 | double lastTime = 0.0; 17 | 18 | public cRegulator() 19 | { 20 | freq = 0.0; 21 | periodTime = 0.0; 22 | } 23 | 24 | public bool isReady() 25 | { 26 | currentTime = GlobalClock.GetTimeInMilliseconds(); 27 | 28 | if ((currentTime - lastTime) >= periodTime * 1000.0) 29 | { 30 | lastTime = currentTime; 31 | return true; 32 | } 33 | 34 | return false; 35 | } 36 | 37 | public void resetByFrequency(double frequency) 38 | { 39 | this.freq = frequency; 40 | this.periodTime = (frequency > 0.0) ? (1.0 / frequency) : 0.0; 41 | lastTime = GlobalClock.GetTimeInMilliseconds(); 42 | } 43 | public void resetByPeriodTime(float period_time_in_seconds) 44 | { 45 | this.periodTime = period_time_in_seconds; 46 | this.freq = (periodTime > 0.0) ? (1.0 / periodTime) : 0.0; 47 | lastTime = GlobalClock.GetTimeInMilliseconds(); 48 | } 49 | public double getPeriodTime() 50 | { 51 | return periodTime; 52 | } 53 | public double getFrequency() 54 | { 55 | return freq; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /platformerGame/Rendering/RenderGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | 9 | namespace platformerGame.Rendering 10 | { 11 | class RenderGroup : Drawable 12 | { 13 | List objects = new List(); 14 | string id = ""; 15 | 16 | public RenderGroup() 17 | { 18 | 19 | } 20 | 21 | // Ha valaki nem tudja hova kell hajózni, egyik szél se jó neki. 22 | 23 | public IEnumerable Objects 24 | { 25 | get { return this.objects;} 26 | } 27 | 28 | public void Add(IDrawable obj) 29 | { 30 | 31 | this.objects.Add(obj); 32 | } 33 | 34 | public virtual void PreRender(float alpha) 35 | { 36 | 37 | } 38 | 39 | public void Draw(RenderTarget target, RenderStates states) 40 | { 41 | 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /platformerGame/Rendering/cAnimatedSpriteRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | 11 | namespace platformerGame.Rendering 12 | { 13 | class cAnimatedSpriteRenderer : cBaseRenderer 14 | { 15 | public cAnimation AnimationSrc { get; set; } 16 | 17 | public cAnimatedSpriteRenderer(string sprite_id, MyIntRect view_offset_rect = null, bool repeat = false) : base() 18 | { 19 | AnimationInfo info = cAnimationAssets.Get(sprite_id); 20 | 21 | if(view_offset_rect != null) 22 | { 23 | info.ViewOffsetRect = view_offset_rect; 24 | } 25 | 26 | info.Repeat = repeat; 27 | AnimationSrc = new cAnimation(info); 28 | } 29 | 30 | protected cAnimatedSpriteRenderer(cAnimatedSpriteRenderer other) : base(other) 31 | { 32 | this.AnimationSrc = new cAnimation(other.AnimationSrc.AnimData); 33 | } 34 | 35 | // by: https://stackoverflow.com/questions/19119623/clone-derived-class-from-base-class-method 36 | public override cBaseRenderer DeepCopy() 37 | { 38 | return new cAnimatedSpriteRenderer(this); 39 | } 40 | 41 | public override void Update(float step_time) 42 | { 43 | AnimationSrc.Update(); 44 | } 45 | 46 | public override void Draw(RenderTarget destination, Vector2f pos) 47 | { 48 | AnimationSrc.RenderCentered(destination, pos); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /platformerGame/Rendering/cAnimationAssets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.Graphics; 7 | using platformerGame.Utilities; 8 | 9 | namespace platformerGame.Rendering 10 | { 11 | class AnimationInfo 12 | { 13 | public Texture refTexture { get; set; } 14 | public List Frames { get; set; } 15 | public MyIntRect ViewOffsetRect { get; set; } 16 | public bool Repeat { get; set; } 17 | 18 | public AnimationInfo(Texture texture, IEnumerable frames, MyIntRect view_offset, bool repeat = false) 19 | { 20 | this.refTexture = texture; // assets.GetTexture(texture_name); 21 | this.Frames = new List(frames); 22 | this.ViewOffsetRect = view_offset; 23 | this.Repeat = repeat; 24 | } 25 | 26 | /* 27 | public AnimationInfo(Texture texture, IEnumerable frames, MyIntRect view_offset, bool repeat = false) 28 | { 29 | this.refTexture = texture; 30 | this.Frames = new List(frames); 31 | this.ViewOffsetRect = view_offset; 32 | this.Repeat = repeat; 33 | } 34 | */ 35 | 36 | public AnimationInfo(AnimationInfo other) 37 | { 38 | this.refTexture = other.refTexture; 39 | this.Frames = new List(other.Frames.ToArray()); 40 | this.ViewOffsetRect = other.ViewOffsetRect; 41 | this.Repeat = other.Repeat; 42 | } 43 | 44 | public void setFramesByRef(List ref_frames) 45 | { 46 | this.Frames = ref_frames; 47 | } 48 | 49 | public AnimationInfo DeepCopy() 50 | { 51 | return new AnimationInfo(this); 52 | } 53 | } 54 | 55 | class cAnimationAssets 56 | { 57 | static Dictionary framesContainer = new Dictionary(); 58 | 59 | static cAnimationAssets() 60 | { 61 | // framesContainer 62 | } 63 | 64 | public static IEnumerable getLoopedFull(int rows, int columns, int frame_width, int frame_height) 65 | { 66 | for (int i = 0; i < rows; i++) 67 | { 68 | for (int j = 0; j < columns; j++) 69 | { 70 | yield return new MyIntRect(j * frame_width, i * frame_height, frame_width, frame_height); 71 | } 72 | } 73 | } 74 | 75 | public static IEnumerable getLoopedRow(int start_row, int start_column, int num_frames, int frame_width, int frame_height) 76 | { 77 | for (int f = 0; f < num_frames; f++) 78 | { 79 | yield return new MyIntRect((start_column + f) * frame_width, start_row * frame_height, frame_width, frame_height); 80 | } 81 | } 82 | 83 | public static void LoadAnimations(AssetContext assets) 84 | { 85 | framesContainer.Add("coins-gold", new AnimationInfo(assets.GetTexture("coins"), getLoopedRow(0, 0, 8, 16, 16), new MyIntRect(0,0,16,16))); 86 | framesContainer.Add("coins-silver", new AnimationInfo(assets.GetTexture("coins"), getLoopedRow(1, 0, 8, 16, 16), new MyIntRect(0, 0, 16, 16))); 87 | framesContainer.Add("coins-copper", new AnimationInfo(assets.GetTexture("coins"), getLoopedRow(2, 0, 8, 16, 16), new MyIntRect(0, 0, 16, 16))); 88 | framesContainer.Add("side-explosion1", new AnimationInfo(assets.GetTexture("side_explosion1"), getLoopedFull(3, 5, 96, 96), new MyIntRect(0, 0, 96, 96))); 89 | framesContainer.Add("side-explosion2", new AnimationInfo(assets.GetTexture("explosion512"), getLoopedFull(3,5,104,100), new MyIntRect(0, 0, 104, 100))); 90 | framesContainer.Add("simple-explosion1", new AnimationInfo(assets.GetTexture("explosion32_B"), getLoopedFull(4, 4, 32, 32), new MyIntRect(0, 0, 32, 32))); 91 | framesContainer.Add("simple-explosion2", new AnimationInfo(assets.GetTexture("explosion32"), getLoopedFull(4, 4, 32, 32), new MyIntRect(0, 0, 32, 32))); 92 | framesContainer.Add("simple-explosion3", new AnimationInfo(assets.GetTexture("explosion196_C"), getLoopedFull(4, 4, 49, 49), new MyIntRect(0, 0, 49, 49))); 93 | framesContainer.Add("flash-black", new AnimationInfo(assets.GetTexture("flash_black_128"), getLoopedFull(4,4,128,128), new MyIntRect(0, 0, 128, 128))); 94 | } 95 | 96 | public static void ClearAll() 97 | { 98 | framesContainer.Clear(); 99 | } 100 | 101 | public static AnimationInfo Get(string id) 102 | { 103 | AnimationInfo inf; 104 | if(framesContainer.TryGetValue(id, out inf)) 105 | { 106 | return inf; 107 | } 108 | 109 | return null; 110 | 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /platformerGame/Rendering/cBaseRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | 10 | namespace platformerGame.Rendering 11 | { 12 | abstract class cBaseRenderer 13 | { 14 | protected RenderStates renderStates; 15 | 16 | public cBaseRenderer() 17 | { 18 | this.renderStates = new RenderStates(BlendMode.Alpha); 19 | } 20 | 21 | protected cBaseRenderer(cBaseRenderer other) 22 | { 23 | this.renderStates = other.renderStates; 24 | } 25 | 26 | // by: https://stackoverflow.com/questions/19119623/clone-derived-class-from-base-class-method 27 | public abstract cBaseRenderer DeepCopy(); 28 | 29 | public abstract void Update(float step_time); 30 | public abstract void Draw(RenderTarget destination, Vector2f pos); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /platformerGame/Rendering/cSpriteRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Utilities; 10 | 11 | namespace platformerGame.Rendering 12 | { 13 | class cSpriteRenderer : cBaseRenderer 14 | { 15 | Sprite sprite; 16 | 17 | public cSpriteRenderer(string texture_name, MyIntRect texture_rect, AssetContext assets) : base() 18 | { 19 | this.sprite = new Sprite(assets.GetTexture(texture_name)); 20 | 21 | this.sprite.TextureRect = texture_rect.AsSfmlIntRect(); 22 | //this.sprite.Scale = new Vector2f(0.5f, 0.5f); 23 | //this.sprite.Rotation = (float)cAppMath.RadianToDegress(this.orientation); 24 | 25 | this.sprite.Origin = new Vector2f(texture_rect.Width / 2.0f, texture_rect.Height / 2.0f); 26 | } 27 | 28 | protected cSpriteRenderer(cSpriteRenderer other) : base(other) 29 | { 30 | this.sprite = new Sprite(other.sprite); 31 | //this.sprite.TextureRect = other.sprite.TextureRect; 32 | } 33 | 34 | public override cBaseRenderer DeepCopy() 35 | { 36 | return new cSpriteRenderer(this); 37 | } 38 | 39 | public override void Update(float step_time) 40 | { 41 | // empty function 42 | } 43 | 44 | public override void Draw(RenderTarget destination, Vector2f pos) 45 | { 46 | sprite.Position = pos; 47 | destination.Draw(sprite, renderStates); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /platformerGame/SfmlApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using SFML.Window; 4 | using SFML.Graphics; 5 | using SFML.System; 6 | using System.Threading; 7 | 8 | using OverlordEngine.Utilities; 9 | 10 | namespace OverlordEngine 11 | { 12 | class SfmlApp 13 | { 14 | RenderWindow mainWindow; 15 | Vector2u windowSize; 16 | Utilities.Timer appTimer; 17 | bool appRunning; 18 | 19 | IGame game = null; 20 | 21 | Color clearColor; 22 | 23 | Text timeText; 24 | 25 | View defaultView; 26 | 27 | bool vsync = false; 28 | 29 | public SfmlApp(IGame refGame) 30 | { 31 | this.game = refGame; 32 | } 33 | 34 | private void setupSFML() 35 | { 36 | windowSize = new Vector2u(1280, 720); 37 | 38 | //if WPF: m_MainWindow = new RenderWindow(formHandle); 39 | mainWindow = new RenderWindow(new VideoMode(windowSize.X, windowSize.Y, 32), "Platformer", Styles.Close); 40 | mainWindow.SetVisible(true); 41 | activateVSYNC(); 42 | mainWindow.SetFramerateLimit(0); 43 | mainWindow.SetKeyRepeatEnabled(false); 44 | 45 | mainWindow.Closed += new EventHandler(OnClosed); 46 | mainWindow.KeyPressed += new EventHandler(OnKeyPressed); 47 | mainWindow.Resized += new EventHandler(OnResized); 48 | mainWindow.MouseButtonPressed += new EventHandler(OnMouseButtonPressed); 49 | 50 | 51 | clearColor = new Color(0, 0, 0, 255); 52 | 53 | this.defaultView = mainWindow.DefaultView; 54 | //resource-ok betöltése (font-ok és textúrák, képek a játékhoz) 55 | AssetManager.LoadResources(); 56 | } 57 | 58 | private void init() 59 | { 60 | setupSFML(); 61 | 62 | appTimer = new Utilities.Timer(); 63 | //ChangeGameState( new cGameScene(this) ); 64 | 65 | 66 | //Idő szöveg 67 | timeText = new Text("", AssetManager.GetFont("pf_tempesta_seven")); 68 | timeText.Position = new Vector2f(this.defaultView.Size.X-500, 30); 69 | timeText.CharacterSize = 28; // in pixels, not points! 70 | timeText.FillColor = Color.White; 71 | timeText.Style = Text.Styles.Bold; 72 | 73 | GlobalClock.Start(); 74 | 75 | game.Init(); 76 | 77 | appRunning = true; 78 | 79 | } 80 | 81 | private void toggleVSYNC() 82 | { 83 | vsync = !vsync; 84 | MainWindow.SetVerticalSyncEnabled(vsync); 85 | } 86 | 87 | private void activateVSYNC() 88 | { 89 | this.vsync = true; 90 | mainWindow.SetVerticalSyncEnabled(true); 91 | } 92 | 93 | private void deactivateVSYNC() 94 | { 95 | this.vsync = false; 96 | mainWindow.SetVerticalSyncEnabled(false); 97 | } 98 | 99 | private void beforeUpdate() 100 | { 101 | game.OnBeforeUpdate(); 102 | } 103 | 104 | private void updateFixed(float step_time) 105 | { 106 | game.OnUpdateFixed(step_time); 107 | } 108 | 109 | private void updateVariable(float stepTime) 110 | { 111 | game.OnUpdateVariable(stepTime); 112 | } 113 | 114 | private void preRender(float alpha) 115 | { 116 | game.OnPreRender(alpha); 117 | } 118 | 119 | private void render(float alpha) 120 | { 121 | mainWindow.Clear(clearColor); 122 | 123 | game.OnRender(mainWindow); 124 | 125 | mainWindow.Display(); 126 | } 127 | 128 | private void mainLoop() 129 | { 130 | // m_Timer.Start(); 131 | 132 | Clock timer = new Clock(); 133 | timer.Restart(); 134 | 135 | const int MAX_FRAMESKIP = 5; 136 | 137 | float time, lastTime; 138 | time = timer.ElapsedTime.AsSeconds(); 139 | lastTime = time; 140 | 141 | float delta = 1.0f; 142 | float maxDelta = 0.25f; //0.25f 143 | float acc = 0; 144 | float stepTime = Constants.STEP_TIME; 145 | int loops; 146 | float alpha = 0.0f; 147 | 148 | while (appRunning) 149 | { 150 | 151 | time = timer.ElapsedTime.AsSeconds(); 152 | delta = time - lastTime; 153 | lastTime = time; 154 | 155 | //m_MainWindow.DispatchEvents(); 156 | 157 | //m_DeltaTime = m_Timer.GetDeltaTime(); 158 | //m_FPS = 1.0f / m_DeltaTime; 159 | 160 | if (delta > maxDelta) 161 | delta = maxDelta; 162 | 163 | 164 | acc += delta; 165 | 166 | /* 167 | float lagTreshold = MAX_FRAMESKIP * stepTime; 168 | if (acc > lagTreshold) 169 | { 170 | acc = lagTreshold; 171 | } 172 | */ 173 | 174 | beforeUpdate(); 175 | 176 | loops = 0; 177 | while (acc >= stepTime) 178 | { 179 | mainWindow.DispatchEvents(); 180 | updateFixed(stepTime); 181 | acc -= stepTime; 182 | 183 | loops++; 184 | 185 | if(loops >= MAX_FRAMESKIP) 186 | { 187 | acc = 0.0f; 188 | break; 189 | } 190 | 191 | } 192 | 193 | updateVariable(1.0f); 194 | 195 | alpha = acc / stepTime; 196 | preRender(alpha); 197 | render(alpha); 198 | } 199 | } 200 | 201 | 202 | public void destroy() 203 | { 204 | game.Destroy(); 205 | mainWindow.Close(); 206 | } 207 | 208 | public void Run() 209 | { 210 | init(); 211 | mainLoop(); 212 | destroy(); 213 | } 214 | 215 | /// 216 | /// Pl. kilépés menüre gombra kattintanak 217 | /// 218 | public void CloseApp() 219 | { 220 | appRunning = false; 221 | } 222 | 223 | /* 224 | public double FPS 225 | { 226 | get { return m_FPS; } 227 | } 228 | */ 229 | 230 | /* 231 | public void ChangeGameState(cGameScene new_state) 232 | { 233 | if(game != null) 234 | game.Exit(); 235 | 236 | //m_LastState = m_CurrentState; 237 | game = new_state; 238 | game.Enter(); 239 | } 240 | */ 241 | 242 | private void OnResized(object sender, SizeEventArgs e) 243 | { 244 | var view = mainWindow.GetView(); 245 | view.Size = new Vector2f(windowSize.X, windowSize.Y); // (e.Width, e.Height); 246 | mainWindow.SetView(view); 247 | } 248 | 249 | private void OnClosed(object sender, EventArgs e) 250 | { 251 | appRunning = false; 252 | } 253 | 254 | private void OnKeyPressed(object sender, KeyEventArgs e) 255 | { 256 | 257 | if (e.Code == Keyboard.Key.Escape) 258 | appRunning = false; 259 | 260 | if (e.Code == Keyboard.Key.V) 261 | toggleVSYNC(); 262 | 263 | game.OnKeyPressed(e); 264 | } 265 | 266 | private void OnMouseButtonPressed(object sender, MouseButtonEventArgs e) 267 | { 268 | game.OnSingleMouseClick(e); 269 | } 270 | 271 | 272 | public RenderWindow MainWindow 273 | { 274 | get { return mainWindow; } 275 | } 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /platformerGame/ShakeScreen.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.System; 8 | using platformerGame.Utilities; 9 | 10 | namespace platformerGame 11 | { 12 | static class ShakeScreen 13 | { 14 | static Vector2f m_DefaultCenter; 15 | static Vector2f m_Offset; 16 | 17 | static Vector2f m_CurrentCenterPos; 18 | static float m_CurrentRadius; 19 | static float m_CurrentAngle; 20 | 21 | static float m_StartRadius; 22 | static float m_MinShakeRadius; 23 | static float m_DiminishFactor; 24 | 25 | static bool shaking; 26 | 27 | static ShakeScreen() 28 | { 29 | shaking = false; 30 | } 31 | 32 | public static void Init(Vector2f default_center) 33 | { 34 | m_DefaultCenter = default_center; 35 | } 36 | 37 | public static void StopShake() 38 | { 39 | shaking = false; 40 | m_Offset = new Vector2f(0.0f, 0.0f); 41 | m_CurrentCenterPos = new Vector2f(0.0f, 0.0f); //m_DefaultCenter; 42 | } 43 | //===================================================================================================== 44 | public static void StartShake(float start_radius = 5.0f, float min_shake_radius = 1.0f, float dimin_factor = 0.925f) 45 | { 46 | shaking = true; 47 | m_CurrentCenterPos = m_DefaultCenter; 48 | //m_Offset = new Vector2f(0.0f, 0.0f); 49 | m_CurrentAngle = (float)AppRandom.GetRandomNumber(0, 360); 50 | m_CurrentRadius = start_radius; 51 | m_MinShakeRadius = min_shake_radius; 52 | m_DiminishFactor = dimin_factor; 53 | } 54 | 55 | 56 | public static void Update() 57 | { 58 | if(shaking) 59 | { 60 | m_CurrentRadius *= m_DiminishFactor; //diminish radius each frame 61 | m_CurrentAngle += (150.0f + AppRandom.GetRandomNumber(0, 60)); //pick new angle 62 | float rad = (float)AppMath.DegressToRadian(m_CurrentAngle); 63 | m_Offset = new Vector2f((float)Math.Sin(rad) * m_CurrentRadius, (float)Math.Cos(rad) * m_CurrentRadius); //create offset 2d vector 64 | 65 | m_CurrentCenterPos = m_DefaultCenter + m_Offset; 66 | //set centre of viewport 67 | 68 | if (m_CurrentRadius < m_MinShakeRadius) //2.0f 69 | StopShake(); 70 | 71 | } 72 | 73 | 74 | } 75 | 76 | public static Vector2f Offset 77 | { 78 | get { return m_Offset; } 79 | } 80 | 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /platformerGame/StateBase/IState.cs: -------------------------------------------------------------------------------- 1 | using SFML.Graphics; 2 | 3 | namespace platformerGame.StateBase 4 | { 5 | interface IState 6 | { 7 | void Create(); 8 | void Enter(IState prev_state = null); 9 | void UpdateFixed(float step_time); 10 | void UpdateVariable(); 11 | void Exit(); 12 | } 13 | 14 | interface IVisualStateComponent 15 | { 16 | // rendering calculations, ordering (eg. view position calculation...etc) 17 | void PreRender(float alpha); 18 | void Render(RenderTarget destination); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /platformerGame/Utilities/AppRandom.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.System; 7 | 8 | namespace platformerGame.Utilities 9 | { 10 | class AppRandom 11 | { 12 | private static Random random; 13 | 14 | static AppRandom() 15 | { 16 | random = new Random(); 17 | } 18 | /// 19 | /// Chooses a random item from the given array 20 | /// 21 | /// type of the array 22 | /// 23 | /// 0 to len to choose, if -1, the length of the array used 24 | /// 25 | public static T Choose(T[] array, int len = -1) 26 | { 27 | return array[ random.Next(0, (len < 0) ? array.Length : len) ]; 28 | } 29 | 30 | /// 31 | /// Chooses a random item from the given list 32 | /// 33 | /// 34 | /// 35 | /// 36 | public static T Chooose(List list) 37 | { 38 | return list[random.Next(0, list.Count)]; 39 | } 40 | 41 | /// 42 | /// Gets a random number in the specified range (max param excluded). 43 | /// 44 | /// 45 | /// 46 | /// 47 | public static int GetRandomNumber(int min, int max) 48 | { 49 | return random.Next(min, max); 50 | } 51 | 52 | /// 53 | /// Gets a random float between 0 and 1. 54 | /// 55 | /// 56 | public static float GetRandomFloat() 57 | { 58 | return (float)random.NextDouble(); 59 | } 60 | 61 | public static double GetRandomDouble() 62 | { 63 | return random.NextDouble(); 64 | } 65 | 66 | public static double GetRandomClamped() 67 | { 68 | return GetRandomDouble() - GetRandomDouble(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /platformerGame/Utilities/AppTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using System.Diagnostics; 8 | 9 | using SFML.System; 10 | 11 | namespace platformerGame.Utilities 12 | { 13 | class AppTimer 14 | { 15 | private Stopwatch m_Timer; //SFML beépített clock-ja 16 | 17 | private double m_CurrentTime; 18 | private double m_LastTime; 19 | 20 | public AppTimer() 21 | { 22 | m_Timer = new Stopwatch(); 23 | } 24 | 25 | public void Start() 26 | { 27 | m_Timer.Start(); 28 | m_CurrentTime = m_Timer.Elapsed.TotalSeconds; 29 | 30 | m_LastTime = m_CurrentTime; 31 | } 32 | public double GetCurrentTime() 33 | { 34 | return m_Timer.Elapsed.TotalSeconds; 35 | } 36 | 37 | public double GetCurrentTimeAsMilliseconds() 38 | { 39 | return m_Timer.Elapsed.TotalMilliseconds; 40 | } 41 | /// 42 | /// Megmondja az eltelt időt az előző hívás óta (másodpercben). Frame-nként hívva megmondja a framek között eltelt (delta) időt, amire szükségünk van. 43 | /// 44 | /// 45 | public double GetDeltaTime() 46 | { 47 | m_CurrentTime = GetCurrentTime(); 48 | double dt = m_CurrentTime - m_LastTime; 49 | m_LastTime = m_CurrentTime; 50 | return dt; 51 | } 52 | 53 | public override string ToString() 54 | { 55 | cTimeInfo tinfo = new cTimeInfo(this.GetCurrentTime()); 56 | return tinfo.ToString(); 57 | } 58 | 59 | /* 60 | private Clock m_Timer; //SFML beépített clock-ja 61 | 62 | private float m_CurrentTime; 63 | private float m_LastTime; 64 | public cTimer() 65 | { 66 | m_Timer = new Clock(); 67 | } 68 | 69 | public void Start() 70 | { 71 | m_CurrentTime = m_Timer.Restart().AsSeconds(); 72 | m_LastTime = m_CurrentTime; 73 | } 74 | public float GetCurrentTime() 75 | { 76 | return m_Timer.ElapsedTime.AsSeconds(); 77 | } 78 | 79 | public float GetCurrentTimeAsMilliseconds() 80 | { 81 | return m_Timer.ElapsedTime.AsMilliseconds(); 82 | } 83 | /// 84 | /// Megmondja az eltelt időt az előző hívás óta (másodpercben). Frame-nként hívva megmondja a framek között eltelt (delta) időt, amire szükségünk van. 85 | /// 86 | /// 87 | public float GetDeltaTime() 88 | { 89 | m_CurrentTime = GetCurrentTime(); 90 | float dt = m_CurrentTime - m_LastTime; 91 | m_LastTime = m_CurrentTime; 92 | return dt; 93 | } 94 | 95 | public override string ToString() 96 | { 97 | cTimeInfo tinfo = new cTimeInfo(this.GetCurrentTime()); 98 | return tinfo.ToString(); 99 | } 100 | */ 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /platformerGame/Utilities/Constants.cs: -------------------------------------------------------------------------------- 1 | using SFML.System; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | using SFML.Graphics; 9 | using Newtonsoft.Json; 10 | using Newtonsoft.Json.Linq; 11 | 12 | using System.IO; 13 | 14 | namespace platformerGame.Utilities 15 | { 16 | class Constants 17 | { 18 | public const float STEP_TIME = 1.0f / 60.0f; 19 | public const uint ANIM_FRAME_TIME = 30; //in ms 20 | 21 | public static int TILE_SIZE = 16; 22 | public static int TILE_SIZE_HALF = TILE_SIZE / 2; 23 | 24 | [JsonProperty("monster-walk-speed")] 25 | public static float MONSTER_WALK_SPEED { get; private set; } //300.0f; 26 | 27 | [JsonProperty("player-walk-speed")] 28 | public static float PLAYER_WALK_SPEED { get; private set; } //300.0f; 29 | 30 | [JsonProperty("monster-max-walk-speed")] 31 | public static float MONSTER_MAX_WALK_SPEED { get; private set; } //200.0f; 32 | 33 | [JsonProperty("player-max-walk-speed")] 34 | public static float PLAYER_MAX_WALK_SPEED { get; private set; } //200.0f; 35 | 36 | [JsonProperty("ground-slowdown-factor")] 37 | public static float GROUND_SLOW_DOWN_FACTOR { get; private set; } //0.745f; 38 | 39 | [JsonProperty("air-slowdown-factor")] 40 | public static float AIR_SLOW_DOWN_FACTOR { get; private set; } 41 | 42 | [JsonProperty("jump-speed")] 43 | public static float JUMP_SPEED { get; private set; } //210 250 44 | 45 | [JsonProperty("max-Y-speed")] 46 | public static float MAX_Y_SPEED { get; private set; } //290.0f; //400 47 | 48 | [JsonProperty("gravity")] 49 | public static float GRAVITY { get; private set; } //680 781.25f 50 | 51 | [JsonProperty("jump-gravity")] 52 | public static float JUMP_GRAVITY { get; private set; } //212.5f; 260 53 | 54 | [JsonProperty("bullet-hit-force")] 55 | public static float BULLET_HIT_FORCE { get; private set; } 56 | 57 | [JsonProperty("bullet-start-speed")] 58 | public static float BULLET_START_SPEED { get; private set; } 59 | 60 | [JsonProperty("bullet-texture-name")] 61 | public static string BULLET_TEXTURE_NAME { get; private set; } 62 | 63 | [JsonProperty("default-weapon-firing-frequency")] 64 | public static int DEFAULT_WEAPON_FIRING_FREQUENCY { get; private set; } 65 | 66 | [JsonProperty("friction")] 67 | public static float FRICTION { get; private set; } //0.02f; 68 | 69 | [JsonProperty("restitution")] 70 | public static float RESTITUTION { get; private set; } //0.1f; 71 | 72 | [JsonProperty("glue")] 73 | public static float GLUE { get; private set; } //0.01f; 74 | 75 | [JsonProperty("character-frame-width")] 76 | public static int CHAR_FRAME_WIDTH { get; private set; } 77 | 78 | [JsonProperty("character-frame-height")] 79 | public static int CHAR_FRAME_HEIGHT { get; private set; } //48 80 | 81 | [JsonProperty("player-texture-name")] 82 | public static string PLAYER_TEXTURE_NAME { get; private set; } 83 | 84 | [JsonProperty("monster-texture-name")] 85 | public static string MONSTER_TEXTURE_NAME { get; private set; } 86 | 87 | [JsonProperty("monster-max-health")] 88 | public static int MONSTER_MAX_HEALTH { get; private set; } 89 | 90 | [JsonProperty("character-collision-rect")] 91 | public static MyIntRect CHAR_COLLISON_RECT { get; private set; } // = new IntRect(10, 0, 22, 32); //32-10 = 22 | 10:left, 32:width 92 | 93 | [JsonProperty("character-view-rect")] 94 | public static MyIntRect CHAR_VIEW_RECT { get; private set; } // = new IntRect(5, 0, 27, 32); 95 | 96 | [JsonProperty("lightmap-color")] 97 | public static Color LIGHTMAP_COLOR { get; private set; } 98 | 99 | [JsonProperty("background-color")] 100 | public static Color BACKGROUND_COLOR { get; private set; } 101 | 102 | [JsonProperty("font-names")] 103 | public static string[] FONT_NAMES { get; private set; } 104 | 105 | [JsonProperty("texture-names")] 106 | public static string[] TEXTURES_NAMES { get; private set; } 107 | 108 | [JsonProperty("sound-names")] 109 | public static string[] SOUND_NAMES { get; private set; } 110 | 111 | [JsonProperty("bg-texture")] 112 | public static string BG_TEXTURE { get; private set; } 113 | 114 | static Constants() 115 | { 116 | } 117 | 118 | public static void Load() 119 | { 120 | if (File.Exists("constants.json")) 121 | { 122 | string json = File.ReadAllText(@"constants.json"); 123 | FromJson(json); 124 | } 125 | else 126 | throw new FileNotFoundException("The constants.json file is missing."); 127 | } 128 | 129 | private static Constants FromJson(string json) => JsonConvert.DeserializeObject(json, new JsonSerializerSettings 130 | { 131 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 132 | DateParseHandling = DateParseHandling.None, 133 | } 134 | ); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /platformerGame/Utilities/MyRect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.Graphics; 7 | 8 | namespace platformerGame.Utilities 9 | { 10 | class MyRect where T : struct 11 | { 12 | public T Left { get; set; } 13 | public T Top { get; set; } 14 | public T Width { get; set; } 15 | public T Height { get; set; } 16 | 17 | public MyRect() 18 | { 19 | Left = Top = Width = Height = default(T); 20 | } 21 | 22 | public MyRect(T left, T top, T w, T h) 23 | { 24 | this.Left = left; 25 | this.Top = top; 26 | this.Width = w; 27 | this.Height = h; 28 | } 29 | 30 | public MyRect(MyRect other) : this(other.Left,other.Top,other.Width,other.Height) 31 | { 32 | } 33 | 34 | public MyRect DeepCopy() 35 | { 36 | return new MyRect(this); 37 | } 38 | 39 | public MyRect ShallowCopy() 40 | { 41 | return (MyRect)this.MemberwiseClone(); 42 | } 43 | } 44 | 45 | class MyIntRect : MyRect 46 | { 47 | 48 | public MyIntRect() : base() 49 | { 50 | } 51 | 52 | public MyIntRect(int left, int top, int w, int h) : base(left,top,w,h) 53 | { 54 | } 55 | 56 | public MyIntRect(MyIntRect other) : base(other.Left, other.Top, other.Width, other.Height) 57 | { 58 | } 59 | 60 | public new MyIntRect DeepCopy() 61 | { 62 | return new MyIntRect(this); 63 | } 64 | 65 | public IntRect AsSfmlIntRect() 66 | { 67 | return new IntRect(Left, Top, Width, Height); 68 | } 69 | 70 | } 71 | 72 | 73 | class MyFloatRect : MyRect 74 | { 75 | public MyFloatRect() : base() 76 | { 77 | } 78 | 79 | public MyFloatRect(float left, float top, float w, float h) : base(left, top, w, h) 80 | { 81 | } 82 | 83 | public MyFloatRect(MyFloatRect other) : base(other.Left, other.Top, other.Width, other.Height) 84 | { 85 | } 86 | 87 | public new MyFloatRect DeepCopy() 88 | { 89 | return new MyFloatRect(this); 90 | } 91 | 92 | public FloatRect AsSfmlFloatRect() 93 | { 94 | return new FloatRect(Left, Top, Width, Height); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /platformerGame/Utilities/ProbabilityRoll.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Utilities 8 | { 9 | /// 10 | /// Weight - value table. Seed the table with weight - value pairs, 11 | /// then by using roll() function, itt will pick randomly a weight(proportion), 12 | /// and then returns the specified type of value. 13 | /// Bigger weight, bigger chance... 14 | /// NOTE: strinsg has no default constructor, so cant be used 15 | /// 16 | /// T is the type of the value 17 | class ProbabilityRoll where T : new() 18 | { 19 | /// 20 | /// the first type of the tuple is weight, second is value 21 | /// 22 | List< Tuple > probabilityTable; 23 | 24 | public ProbabilityRoll() 25 | { 26 | probabilityTable = new List>(); 27 | } 28 | 29 | /// 30 | /// Uploads the probability table by adding weights - values pairs. 31 | /// 32 | /// array of the weight - value pairs 33 | /// 34 | public void seed(Tuple[] wv_pairs) 35 | { 36 | probabilityTable.Clear(); 37 | 38 | foreach (var p in wv_pairs) 39 | { 40 | probabilityTable.Add(p); 41 | } 42 | } 43 | 44 | /// 45 | /// Uploads the probability table with weights and values. 46 | /// Arrays must have same sizes. 47 | /// 48 | /// array of weights 49 | /// array of values 50 | /// false, if the length of weights and values not equals, else true. 51 | public bool seed(int[] weights, T[] values) 52 | { 53 | if(weights.Length != values.Length) 54 | { 55 | return false; 56 | } 57 | 58 | int len = weights.Length; 59 | probabilityTable.Clear(); 60 | 61 | for(int i = 0; i < len; i++) 62 | { 63 | probabilityTable.Add(new Tuple(weights[i], values[i])); 64 | } 65 | 66 | return true; 67 | } 68 | 69 | public void add(int weight, T value) 70 | { 71 | probabilityTable.Add(new Tuple(weight, value)); 72 | } 73 | 74 | public void clear() 75 | { 76 | probabilityTable.Clear(); 77 | } 78 | 79 | private T lookupValue(int x) 80 | { 81 | // assume 0 ≤ x < sum_of_weights 82 | int cumulative_weight = 0; 83 | 84 | for (var row = 0; row < probabilityTable.Count; row++) 85 | { 86 | cumulative_weight += probabilityTable[row].Item1; 87 | if (x < cumulative_weight) 88 | { 89 | return probabilityTable[row].Item2; 90 | } 91 | } 92 | 93 | // should never run, because the condition inside for loop should evaulate true sometime, 94 | // so we always return from there. 95 | return default(T); //Activator.CreateInstance(); 96 | } 97 | 98 | public T roll(bool use_empty = false) 99 | { 100 | int sum_of_weights = 0; 101 | for (var row = 0; row < probabilityTable.Count; row++) 102 | { 103 | 104 | sum_of_weights += probabilityTable[row].Item1; 105 | } 106 | 107 | int x = AppRandom.GetRandomNumber(0, use_empty ? 100 : sum_of_weights); 108 | return lookupValue(x); 109 | } 110 | 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /platformerGame/Utilities/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | 9 | namespace platformerGame.Utilities 10 | { 11 | public static class Utils 12 | { 13 | public static readonly Color RED = new Color(255, 82, 82); 14 | public static readonly Color BLUE = new Color(99, 196, 236); 15 | 16 | //========================================================================================================== 17 | public static Color GetRandomRedColor() 18 | { 19 | Color c = GetRandomColor(200, 255, 5, 90, 5, 90); // (160, 255, 20, 80, 20, 80); 20 | return c; 21 | } 22 | //========================================================================================================== 23 | public static Color GetRandomOrangeColor() 24 | { 25 | Color c = GetRandomColor(220, 255, 130, 160, 50, 70); // (160, 255, 20, 80, 20, 80); 26 | return c; 27 | } 28 | //========================================================================================================== 29 | public static Color GetRandomGreenColor() 30 | { 31 | Color c = GetRandomColor(20, 100, 160, 255, 20, 100); 32 | return c; 33 | } 34 | //========================================================================================================== 35 | public static Color GetRandomBlueColor() 36 | { 37 | Color c = GetRandomColor(37, 99, 150, 196, 220, 236); 38 | return c; 39 | } 40 | //========================================================================================================== 41 | public static Color GetRandomColor(byte minR, byte maxR, byte minG, byte maxG, byte minB, byte maxB) 42 | { 43 | Color c = new Color(); 44 | 45 | c.R = AppMath.GetRandomByte(minR, maxR); 46 | c.G = AppMath.GetRandomByte(minG, maxG); 47 | c.B = AppMath.GetRandomByte(minB, maxB); 48 | c.A = 255; 49 | return c; 50 | } 51 | 52 | //========================================================================================================== 53 | public static void Swap(ref T a, ref T b) 54 | { 55 | T c = a; 56 | a = b; 57 | b = c; 58 | } 59 | //========================================================================================================== 60 | public static Color GetSfmlColorFromHex(string hex_color) 61 | { 62 | System.Drawing.Color c = System.Drawing.ColorTranslator.FromHtml(hex_color); 63 | return new Color(c.R, c.G, c.B, c.A); 64 | } 65 | //========================================================================================================== 66 | public static void RemoveAll(this Dictionary dict, Func, bool> match) 67 | { 68 | foreach (var cur in dict.Where(match).ToList()) 69 | { 70 | dict.Remove(cur.Key); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /platformerGame/Utilities/cTimeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame.Utilities 8 | { 9 | class cTimeInfo 10 | { 11 | double seconds; 12 | 13 | public cTimeInfo() 14 | { 15 | seconds = 0.0f; 16 | } 17 | 18 | public cTimeInfo(double sec) 19 | { 20 | seconds = sec; 21 | } 22 | public double Seconds 23 | { 24 | get { return seconds; } 25 | set { seconds = value; } 26 | } 27 | 28 | public override string ToString() 29 | { 30 | int min = (int)(seconds / 60); 31 | int sec = ((int)seconds % 60); 32 | int sec2 = sec / 10; 33 | int sec3 = sec % 10; 34 | 35 | return String.Format("{0}:{1}{2}", min, sec2, sec3); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /platformerGame/cAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | using platformerGame.Rendering; 10 | using platformerGame.Utilities; 11 | 12 | namespace platformerGame 13 | { 14 | class cAnimation 15 | { 16 | AnimationInfo animData; 17 | 18 | bool m_FlipHorizontally; 19 | bool m_FlipVertically; 20 | 21 | uint m_FrameTime; //in milliseconds 22 | uint m_StartFrame; 23 | 24 | int m_CurrentFrame; 25 | double m_CurrentAnimTime; 26 | double m_LastAnimTime; 27 | 28 | // MyIntRect viewOffsetRect; //view rect offsets inside animation rect 29 | 30 | public bool Active { get; set; } 31 | 32 | public cAnimation(Texture sprite_sheet, MyIntRect view_offset_rect) 33 | { 34 | animData = new AnimationInfo(sprite_sheet, new List(), view_offset_rect); 35 | init(); 36 | } 37 | 38 | public cAnimation(AnimationInfo ref_anim) 39 | { 40 | this.animData = ref_anim; 41 | this.SetFrames(ref_anim.Frames); 42 | init(); 43 | } 44 | 45 | public void init() 46 | { 47 | m_FlipHorizontally = false; 48 | m_FlipVertically = false; 49 | m_CurrentFrame = 0; 50 | Active = true; 51 | m_CurrentAnimTime = GlobalClock.GetTimeInMilliseconds(); 52 | m_FrameTime = Constants.ANIM_FRAME_TIME; 53 | m_LastAnimTime = m_CurrentAnimTime; 54 | } 55 | 56 | private bool _isReadyForNextFrame() 57 | { 58 | m_CurrentAnimTime = GlobalClock.GetTimeInMilliseconds(); 59 | return (m_CurrentAnimTime - m_LastAnimTime >= m_FrameTime); 60 | } 61 | 62 | public void Update() 63 | { 64 | if (this.GetSize() > 1) 65 | { 66 | if (_isReadyForNextFrame()) 67 | { 68 | m_LastAnimTime = GlobalClock.GetTimeInMilliseconds(); 69 | 70 | m_CurrentFrame += 1; 71 | 72 | if (m_CurrentFrame >= this.GetSize()) //myCurrentFrame < 0 73 | { 74 | if(this.animData.Repeat) 75 | { 76 | m_CurrentFrame = 0; 77 | return; 78 | } 79 | m_CurrentFrame = this.GetSize() - 1; 80 | Active = false; 81 | } 82 | } 83 | } 84 | else 85 | m_CurrentFrame = 0; 86 | 87 | } 88 | 89 | public void RenderCentered(RenderTarget destination, Vector2f pos) 90 | { 91 | MyIntRect frame = this.GetCurrentFrame().DeepCopy(); 92 | 93 | frame.Left += this.animData.ViewOffsetRect.Left; 94 | frame.Top += this.animData.ViewOffsetRect.Top; 95 | 96 | frame.Width = this.animData.ViewOffsetRect.Width; 97 | frame.Height = this.animData.ViewOffsetRect.Height; 98 | 99 | DrawingBase.DrawTextureUseCenter(destination, 100 | pos, 101 | this.GetTexture(), 102 | frame, 103 | Color.White, 104 | 0.0f, 105 | 1.0f, //SCALE_FACTOR, 106 | false, //p_myCurrentAnim->IsFlippedHorizontally(), 107 | false, 108 | BlendMode.Add, 109 | null); 110 | } 111 | 112 | public void Render(RenderTarget destination, Vector2f pos) //MyIntRect view_rect = new MyIntRect() 113 | { 114 | MyIntRect frame = this.GetCurrentFrame().DeepCopy(); //.DeepCopy is very important for drawing!! 115 | 116 | frame.Left += this.animData.ViewOffsetRect.Left; 117 | frame.Top += this.animData.ViewOffsetRect.Top; 118 | 119 | frame.Width = this.animData.ViewOffsetRect.Width; 120 | frame.Height = this.animData.ViewOffsetRect.Height; 121 | 122 | /* 123 | cRenderFunctions.DrawTextureSimple( destination, 124 | pos, 125 | this.GetSpriteSheet(), 126 | frame, 127 | Color.White, 128 | BlendMode.Alpha 129 | ); 130 | */ 131 | 132 | 133 | DrawingBase.DrawTexture(destination, 134 | pos, 135 | this.GetTexture(), 136 | frame, 137 | Color.White, 138 | 0.0f, 139 | 1.0f, //SCALE_FACTOR, 140 | false, //p_myCurrentAnim->IsFlippedHorizontally(), 141 | false, 142 | BlendMode.Alpha, 143 | null); 144 | 145 | } 146 | 147 | public void Clear() 148 | { 149 | this.animData.Frames.Clear(); 150 | } 151 | public bool FlipHorizontally 152 | { 153 | get { return m_FlipHorizontally; } 154 | set { m_FlipHorizontally = value; } 155 | } 156 | public bool FlipVertically 157 | { 158 | get { return m_FlipVertically; } 159 | set { m_FlipVertically = value; } 160 | } 161 | 162 | public void AddFrame(MyIntRect rect) 163 | { 164 | this.animData.Frames.Add(rect); 165 | } 166 | 167 | public void SetFrames(List frames) 168 | { 169 | this.animData.Frames = new List(frames); 170 | } 171 | 172 | /* 173 | public void SetSpriteSheet(Texture texture) 174 | { 175 | m_pTexture = texture; 176 | } 177 | */ 178 | public Texture GetTexture() 179 | { 180 | return animData.refTexture; 181 | } 182 | 183 | public AnimationInfo AnimData 184 | { 185 | get { return this.animData; } 186 | } 187 | 188 | public int GetSize() 189 | { 190 | return this.animData.Frames.Count; 191 | } 192 | 193 | public MyIntRect GetCurrentFrame() 194 | { 195 | return GetFrame(m_CurrentFrame); 196 | } 197 | 198 | public MyIntRect GetFrame(int n) 199 | { 200 | //n = cAppMath.Clamp(n, 0, GetSize()); 201 | //n = n < 0 ? 0 : n >= GetSize() ? GetSize() : n; 202 | /* if (m_Frames.Count > 0) 203 | return m_Frames[n]; 204 | else 205 | return new MyIntRect(0, 0, 32, 32);*/ 206 | 207 | return animData.Frames.Count > 0 ? animData.Frames[n] : new MyIntRect(0,0,1,1); 208 | } 209 | 210 | public void SetStartFrame(uint start_frame) { m_StartFrame = start_frame; } 211 | public uint GetStartFrame() {return m_StartFrame;} 212 | 213 | public void SetFrameTime(uint frame_time) { m_FrameTime = frame_time; } 214 | public uint GetFrameTime() {return m_FrameTime;} 215 | 216 | ~cAnimation() 217 | { 218 | 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /platformerGame/cEnvironment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | 10 | using platformerGame.Utilities; 11 | 12 | namespace platformerGame 13 | { 14 | class cEnvironmentItem 15 | { 16 | protected Sprite sprite; 17 | protected AABB bounds; //may differ from drawing bounds 18 | 19 | public cEnvironmentItem(Texture texture) 20 | { 21 | sprite = new Sprite(texture); 22 | bounds = new AABB(); 23 | } 24 | 25 | public cEnvironmentItem(Vector2f pos, Texture texture, AABB _bounds = null) 26 | { 27 | sprite = new Sprite(texture); 28 | sprite.Position = pos; 29 | bounds = _bounds ?? new AABB(pos, new Vector2f(texture.Size.X, texture.Size.Y)); 30 | } 31 | 32 | public Sprite Sprite 33 | { 34 | get { return sprite; } 35 | //set { sprite = value; } 36 | } 37 | 38 | public AABB Bounds 39 | { 40 | get { return bounds; } 41 | set { bounds = value; } 42 | } 43 | } 44 | class cEnvironment 45 | { 46 | List envItems; 47 | 48 | List waterBlocks; 49 | 50 | public cEnvironment() 51 | { 52 | envItems = new List(); 53 | 54 | } 55 | 56 | public void SetWaterBlocks(List wb_from_map) 57 | { 58 | waterBlocks = wb_from_map; 59 | } 60 | public void PlaceItem(Vector2f centre_pos, Texture texture) 61 | { 62 | //TODO: set pos by centre 63 | /* 64 | cEnvironmentItem item = new cEnvironmentItem(); 65 | envItems.Add(item); 66 | */ 67 | } 68 | 69 | public void PlaceOnGround(Vector2f on_ground_pos, Texture texture) 70 | { 71 | float x = on_ground_pos.X - texture.Size.X / 2.0f; 72 | float y = on_ground_pos.Y + Constants.TILE_SIZE - texture.Size.Y; 73 | 74 | cEnvironmentItem item = new cEnvironmentItem(new Vector2f(x,y), texture); 75 | envItems.Add(item); 76 | } 77 | 78 | /// 79 | /// Calculates bounding box for an item on the ground by giving its texture size. 80 | /// 81 | /// 82 | /// 83 | /// 84 | public AABB CalcBBOnGroundByTexture(Vector2f on_ground_pos, Vector2f texture_size) 85 | { 86 | float x = on_ground_pos.X - texture_size.X / 2.0f; 87 | float y = on_ground_pos.Y + Constants.TILE_SIZE - texture_size.Y; 88 | 89 | return new AABB(x, y, texture_size.X, texture_size.Y); 90 | } 91 | public void PlaceOnGround(Vector2f texture_pos, Texture texture, AABB bounding_rect) 92 | { 93 | 94 | cEnvironmentItem item = new cEnvironmentItem(texture_pos, texture, bounding_rect); 95 | envItems.Add(item); 96 | } 97 | 98 | 99 | public void ClearAll() 100 | { 101 | envItems.Clear(); 102 | waterBlocks.Clear(); 103 | } 104 | public void Update(float step_time) 105 | { 106 | foreach (cWaterBlock wb in waterBlocks) 107 | { 108 | wb.Update(step_time); 109 | } 110 | } 111 | 112 | public void RenderWaterBlocks(RenderTarget destination) 113 | { 114 | 115 | foreach (cWaterBlock wb in waterBlocks) 116 | { 117 | wb.Render(destination); 118 | } 119 | } 120 | public void RenderEnvironment(RenderTarget destination) 121 | { 122 | 123 | RenderStates rs = new RenderStates(BlendMode.Alpha); 124 | 125 | foreach (cEnvironmentItem item in envItems) 126 | { 127 | 128 | //destination.Draw(item.Sprite, rs); 129 | #if DEBUG 130 | RectangleShape rect = new RectangleShape(); 131 | rect.Position = item.Bounds.topLeft; 132 | rect.Size = item.Bounds.dims; 133 | rect.OutlineColor = Color.Green; 134 | rect.OutlineThickness = 2.0f; 135 | rect.FillColor = Color.Transparent; 136 | 137 | destination.Draw(rect, rs); 138 | 139 | #else 140 | destination.Draw(item.Sprite, rs); 141 | #endif 142 | } 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /platformerGame/cLight.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.Graphics; 7 | using SFML.System; 8 | 9 | using platformerGame.Utilities; 10 | 11 | namespace platformerGame 12 | { 13 | class cLight 14 | { 15 | public Vector2f Pos { get; set; } //Center 16 | public Vector2f Dir { get; set; } //Direction of the Light 17 | 18 | private Color color; 19 | private Vector3f glColor; 20 | public Color OriginalColor { get; set; } 21 | 22 | public float Opacity { get; set; } 23 | 24 | public float Radius { get; set; } 25 | public float SpreadAngle { get; set; } 26 | 27 | //for light autenuation shader 28 | public float Bleed { get; set; } 29 | public float LinearizeFactor { get; set; } 30 | 31 | public bool Active { get; set; } 32 | 33 | public cLight() 34 | { 35 | Pos = new Vector2f(0, 0); 36 | Dir = new Vector2f(0, 0); 37 | Color = new Color(255, 255, 255, 255); 38 | OriginalColor = color; 39 | Opacity = 255.0f; 40 | Radius = 20.0f; 41 | SpreadAngle = (float)AppMath.TWO_PI; 42 | Bleed = 1.0f; 43 | LinearizeFactor = 0.6f; 44 | Active = true; 45 | } 46 | 47 | public cLight(Vector2f pos) : this() 48 | { 49 | Pos = pos; 50 | } 51 | 52 | public void TurnOn() 53 | { 54 | Color = new Color(OriginalColor); 55 | } 56 | 57 | public void TurnOff() 58 | { 59 | Color = new Color(0, 0, 0, 0); 60 | } 61 | 62 | public Color Color 63 | { 64 | get { return color; } 65 | set 66 | { 67 | color = value; 68 | glColor.X = ((float)color.R / 255.0f); 69 | glColor.Y = ((float)color.G / 255.0f); 70 | glColor.Z = ((float)color.B / 255.0f); 71 | } 72 | } 73 | 74 | public Vector3f GLcolor 75 | { 76 | get { return glColor; } 77 | } 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /platformerGame/cPlayerInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using System.IO; 8 | using System.Xml; 9 | using System.Xml.Serialization; 10 | 11 | 12 | namespace platformerGame 13 | { 14 | public class cPlayerInfo 15 | { 16 | public float Time { get; set; } 17 | public string Level { get; set; } 18 | 19 | public cPlayerInfo() 20 | { 21 | Time = 0.0f; 22 | Level = "no-level"; 23 | } 24 | 25 | 26 | 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /platformerGame/cSpriteState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace platformerGame 8 | { 9 | enum HorizontalFacing 10 | { 11 | FACING_LEFT = 2, 12 | FACING_RIGHT 13 | }; 14 | 15 | enum MotionType 16 | { 17 | STAND = 1, 18 | WALK, 19 | JUMP, 20 | FALL, 21 | LIE 22 | }; 23 | 24 | class cSpriteState 25 | { 26 | private MotionType motionType; 27 | private HorizontalFacing horizontalFacing; 28 | 29 | public HorizontalFacing HorizontalFacing 30 | { 31 | get { return horizontalFacing; } 32 | set { horizontalFacing = value; } 33 | } 34 | 35 | public MotionType MotionType 36 | { 37 | get { return motionType; } 38 | set { motionType = value; } 39 | } 40 | public cSpriteState(MotionType motion, HorizontalFacing h_facing) 41 | { 42 | motionType = motion; 43 | horizontalFacing = h_facing; 44 | } 45 | 46 | public cSpriteState ShallowCopy() 47 | { 48 | return (cSpriteState)this.MemberwiseClone(); 49 | } 50 | public static bool operator ==(cSpriteState a, cSpriteState b) 51 | { 52 | return (a.MotionType == b.MotionType && a.HorizontalFacing == b.HorizontalFacing); 53 | } 54 | 55 | public static bool operator !=(cSpriteState a, cSpriteState b) 56 | { 57 | return (a.MotionType != b.MotionType || a.HorizontalFacing != b.HorizontalFacing); 58 | } 59 | 60 | public static bool operator <(cSpriteState a, cSpriteState b) 61 | { 62 | if (a.MotionType != b.MotionType) 63 | { 64 | return a.MotionType < b.MotionType; 65 | } 66 | 67 | if (a.HorizontalFacing != b.HorizontalFacing) 68 | { 69 | return a.HorizontalFacing < b.HorizontalFacing; 70 | } 71 | 72 | return false; 73 | } 74 | 75 | public static bool operator >(cSpriteState a, cSpriteState b) 76 | { 77 | if (a.MotionType != b.MotionType) 78 | { 79 | return a.MotionType > b.MotionType; 80 | } 81 | 82 | if (a.HorizontalFacing != b.HorizontalFacing) 83 | { 84 | return a.HorizontalFacing > b.HorizontalFacing; 85 | } 86 | 87 | return false; 88 | } 89 | 90 | public override bool Equals(object obj) 91 | { 92 | cSpriteState other = (cSpriteState)obj; 93 | return (this.MotionType == other.MotionType && this.HorizontalFacing == other.HorizontalFacing); 94 | } 95 | 96 | public override int GetHashCode() 97 | { 98 | return (int)motionType ^ (int)horizontalFacing; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /platformerGame/cSpriteStateController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SFML.Graphics; 7 | using SFML.System; 8 | using platformerGame.Utilities; 9 | 10 | namespace platformerGame 11 | { 12 | class cSpriteStateController 13 | { 14 | Dictionary m_SpriteStates; 15 | 16 | cSpriteState m_PrevState; 17 | cSpriteState m_CurrentState; 18 | 19 | cAnimation m_pCurrentAnim; 20 | 21 | public cSpriteStateController() 22 | { 23 | m_SpriteStates = new Dictionary(); 24 | m_pCurrentAnim = null; 25 | } 26 | 27 | public void AddAnimState_by_Full_Texture( cSpriteState state_type, 28 | Texture texture, 29 | int a_frame_width, 30 | int a_frame_height, 31 | int num_columns_of_frames, 32 | int num_rows_of_frames, 33 | uint frame_time ) 34 | { 35 | cAnimation temp = new cAnimation(texture, new MyIntRect()); 36 | //temp.SetSpriteSheet(texture); 37 | 38 | for (int y = 0; y < num_rows_of_frames; y++) 39 | { 40 | for (int x = 0; x < num_columns_of_frames; x++) 41 | { 42 | temp.AddFrame(new MyIntRect(x * a_frame_width, 43 | y * a_frame_height, 44 | a_frame_width, 45 | a_frame_height)); 46 | } 47 | } 48 | 49 | temp.SetFrameTime(frame_time); 50 | temp.SetStartFrame(0); 51 | 52 | //KeyValuePair state_pair = new KeyValuePair(state_type, temp); 53 | 54 | m_SpriteStates.Add(state_type, temp); 55 | } 56 | 57 | public void AddAnimState(cSpriteState state_type, 58 | Texture texture, 59 | int frame_width, 60 | int frame_height, 61 | int start_frame_column, //x 62 | int start_frame_row, //y 63 | uint anim_start_frame, 64 | int num_frames, 65 | uint frame_time, // in ms 66 | MyIntRect view_rect, 67 | bool flip_vertically = false, 68 | bool flip_horizontally = false) 69 | { 70 | if(view_rect.Width == 0 && view_rect.Height == 0) 71 | { 72 | view_rect.Width = frame_width; 73 | view_rect.Height = frame_height; 74 | } 75 | 76 | cAnimation anim = new cAnimation(texture, view_rect); 77 | anim.AnimData.Repeat = true; 78 | 79 | anim.FlipHorizontally = flip_horizontally; 80 | anim.FlipVertically = flip_vertically; 81 | //anim.SetSpriteSheet(texture); 82 | 83 | //float a_frame_width = texture.getSize().x / max_frames; 84 | //float a_frame_height = texture.getSize().y; 85 | 86 | for (int x = 0; x < num_frames; ++x) 87 | { 88 | anim.AddFrame(new MyIntRect((start_frame_column + x) * frame_width, 89 | start_frame_row * frame_height, 90 | frame_width, 91 | frame_height)); 92 | } 93 | 94 | anim.SetFrameTime(frame_time); 95 | anim.SetStartFrame(anim_start_frame); 96 | 97 | //std::pair state_pair = std::pair(state_type, anim); 98 | 99 | m_SpriteStates.Add(state_type, anim); 100 | } 101 | 102 | public void ChangeState(cSpriteState state_type) 103 | { 104 | m_CurrentState = state_type; 105 | 106 | m_pCurrentAnim = m_SpriteStates[state_type]; 107 | } 108 | 109 | public cSpriteState getCurrentState() 110 | { 111 | return m_CurrentState; 112 | } 113 | public void Update(cSpriteState new_sprite_state) 114 | { 115 | //m_PrevState = m_CurrentState; 116 | 117 | m_CurrentState = new_sprite_state; 118 | m_pCurrentAnim = m_SpriteStates[m_CurrentState]; 119 | 120 | //if(m_PrevState != m_CurrentState) 121 | //{ 122 | // m_pCurrentAnim = &m_SpriteStates[m_CurrentState]; 123 | //} 124 | 125 | 126 | m_pCurrentAnim.Update(); 127 | } 128 | 129 | public void Clear() 130 | { 131 | 132 | foreach(cAnimation a in m_SpriteStates.Values) 133 | { 134 | a.Clear(); 135 | } 136 | 137 | m_SpriteStates.Clear(); 138 | } 139 | 140 | public void Render(RenderTarget destination, Vector2f pos) 141 | { 142 | m_pCurrentAnim.Render(destination, pos); 143 | } 144 | 145 | cAnimation GetCurrentAnimation() 146 | { 147 | return m_pCurrentAnim; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /platformerGame/cWaterBlock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Window; 8 | using SFML.System; 9 | using SFML.Graphics; 10 | 11 | using platformerGame.Utilities; 12 | 13 | namespace platformerGame 14 | { 15 | class cWaterNode 16 | { 17 | public Vector2f startPosition; 18 | public Vector2f position; 19 | public Vector2f lastPosition; 20 | public Vector2f velocity; 21 | public Vector2f acceleration; 22 | public Vector2f force; 23 | 24 | //private float factor; 25 | 26 | const float MAX_FORCE = 500.0f; 27 | const float MAX_VELOCITY = 4500.0f; 28 | float SPEED = 0.0f; 29 | public cWaterNode(Vector2f pos, float start_Y) 30 | { 31 | position = pos; 32 | lastPosition = position; 33 | startPosition = new Vector2f(pos.X, start_Y); 34 | //Random r = new Random(); 35 | /* factor = (float)random.Next(-10, 10);*/ 36 | velocity = new Vector2f(0.0f, 0.0f); 37 | force = new Vector2f(); 38 | acceleration = new Vector2f(); 39 | 40 | SPEED = AppRandom.GetRandomNumber(40, 300); 41 | 42 | 43 | } 44 | 45 | public void Update(float step_time) 46 | { 47 | force.Y = (startPosition.Y - position.Y) * SPEED; 48 | //cAppMath.Vec2Truncate(ref force, MAX_FORCE); 49 | 50 | acceleration.Y = force.Y * step_time; 51 | velocity.Y += acceleration.Y * step_time; 52 | 53 | AppMath.Vec2Truncate(ref velocity, MAX_VELOCITY); 54 | 55 | lastPosition = position; 56 | 57 | position.Y += velocity.Y * step_time; // * factor; 58 | 59 | force.Y = 0.0f; 60 | } 61 | } 62 | 63 | class cWaterBlock 64 | { 65 | AABB area; 66 | VertexArray vertices; 67 | 68 | const int MAX_OFFSET_Y = 4; //4 69 | const int MIN_OFFSET_Y = -3; //-3 70 | 71 | int DIVISION = 6; 72 | 73 | float unitLength; 74 | 75 | RenderStates rs = new RenderStates(BlendMode.Alpha); 76 | 77 | List waterNodes; 78 | 79 | public cWaterBlock() 80 | { 81 | 82 | vertices = new VertexArray(PrimitiveType.TrianglesStrip); 83 | 84 | waterNodes = new List(); 85 | 86 | } 87 | 88 | public cWaterBlock(AABB area) 89 | { 90 | this.area = area.ShallowCopy(); 91 | 92 | int divider = Constants.TILE_SIZE; // / 2 93 | DIVISION = (int)(this.area.dims.X / divider); 94 | unitLength = divider; // this.area.dims.X / (float)DIVISION; 95 | 96 | vertices = new VertexArray(PrimitiveType.TrianglesStrip); 97 | 98 | waterNodes = new List(); 99 | 100 | Init(); 101 | } 102 | 103 | public void Init() 104 | { 105 | vertices.Clear(); 106 | 107 | //Color col = new Color(0, 140, 186); //a víz felső színe new Color(239,28,57); 108 | //Color col2 = new Color(20, 92, 147); // alsó színe new Color(217,37,50); 109 | 110 | //Color col = new Color(239,28,57); 111 | //Color col2 = new Color(217,37,50); 112 | 113 | Color col = new Color(15,151,219); 114 | Color col2 = new Color(11,115,163); 115 | 116 | int bottomY = (int)area.rightBottom.Y; 117 | 118 | Vector2f[] points = new Vector2f[DIVISION + 1]; 119 | 120 | 121 | points[0] = new Vector2f(area.topLeft.X, area.topLeft.Y); 122 | points[DIVISION] = new Vector2f(area.rightBottom.X, area.topLeft.Y); 123 | 124 | for (int i = 1; i < points.Length-1; i++) 125 | { 126 | int add = AppRandom.GetRandomNumber(MIN_OFFSET_Y, MAX_OFFSET_Y); 127 | points[i] = new Vector2f(area.topLeft.X + i * unitLength, area.topLeft.Y + add); 128 | } 129 | 130 | vertices.Append(new Vertex(points[0], col)); 131 | 132 | //mindig kettőt adunk hozzá: az alsót és a következő felsőt 133 | for (int i = 0; i < points.Length-1; i++) 134 | { 135 | //bottom 136 | vertices.Append(new Vertex(new Vector2f(points[i].X, bottomY), col2) ); 137 | 138 | //következő 139 | vertices.Append(new Vertex(points[i+1], col)); 140 | 141 | //Itt adunk hozzá egy waternode-ot 142 | waterNodes.Add(new cWaterNode(points[i + 1], area.topLeft.Y)); 143 | } 144 | 145 | vertices.Append(new Vertex(new Vector2f(area.rightBottom.X, bottomY), col2)); 146 | } 147 | public void Update(float step_time) 148 | { 149 | uint vIndex = 0; 150 | uint i = 0; 151 | 152 | do 153 | { 154 | waterNodes[(int)i].Update(step_time * 1.75f); 155 | 156 | //csak a felső csatlakozó vertexeket akarjuk mozgatni, így azokkal foglalkozunk 157 | vIndex = 2 + (i * 2); 158 | 159 | Vector2f vpoint = vertices[vIndex].Position; 160 | vpoint.Y = waterNodes[(int)i].position.Y; 161 | 162 | Vertex vert = vertices[vIndex]; 163 | vert.Position = vpoint; 164 | vertices[vIndex] = vert; 165 | 166 | i++; 167 | 168 | } 169 | while (i < waterNodes.Count-1 && vIndex < vertices.VertexCount); 170 | } 171 | 172 | public AABB Area 173 | { 174 | get { return area; } 175 | } 176 | public void Render(RenderTarget destination) 177 | { 178 | 179 | destination.Draw(vertices, rs); 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /platformerGame/constants.json: -------------------------------------------------------------------------------- 1 | { 2 | "player-walk-speed": 250.0, 3 | "monster-walk-speed": 250.0, 4 | "player-max-walk-speed": 150.0, 5 | "monster-max-walk-speed": 90.0, 6 | "ground-slowdown-factor": 0.6, 7 | "air-slowdown-factor": 0.95, 8 | "jump-speed": 300.0, 9 | "max-Y-speed": 400.0, 10 | "gravity": 881.25, 11 | "jump-gravity": 460, 12 | "bullet-hit-force": 1000, 13 | "bullet-start-speed": 900, 14 | "default-weapon-firing-frequency": 12, 15 | "friction": 0.1, 16 | "restitution": 0.5, 17 | "glue": 0.001, 18 | "character-frame-width": 32, 19 | "character-frame-height": 32, 20 | "player-texture-name": "player1_char_set", 21 | "monster-texture-name": "monster1_char_set", 22 | "monster-max-health": 12, 23 | "character-collision-rect": { 24 | "Left": 10, 25 | "Top": 0, 26 | "Width": 22, 27 | "Height": 32 28 | }, 29 | "character-view-rect": { 30 | "Left": 5, 31 | "Top": 0, 32 | "Width": 27, 33 | "Height": 32 34 | }, 35 | "lightmap-color": { 36 | "R": 10, 37 | "G": 10, 38 | "B": 10, 39 | "A": 255 40 | }, 41 | "background-color": { 42 | "R": 255, 43 | "G": 255, 44 | "B": 255, 45 | "A": 255 46 | } 47 | } -------------------------------------------------------------------------------- /platformerGame/sfLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using SFML.Graphics; 8 | using SFML.System; 9 | 10 | namespace platformerGame 11 | { 12 | class sfLine : Drawable 13 | { 14 | 15 | private VertexArray vertices; 16 | //private float thickness; 17 | //private Color color; 18 | public sfLine(Vector2f point1, Vector2f point2, Color color, float thickness) 19 | { 20 | Vector2f direction = point2 - point1; 21 | Vector2f unitDirection = direction / (float)Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y); 22 | Vector2f unitPerpendicular = new Vector2f(-unitDirection.Y, unitDirection.X); 23 | 24 | Vector2f offset = (thickness / 2.0f) * unitPerpendicular; 25 | vertices = new VertexArray(PrimitiveType.Quads); 26 | vertices.Append(new Vertex(point1 + offset, color)); 27 | vertices.Append(new Vertex(point2 + offset, color)); 28 | vertices.Append(new Vertex(point2 - offset, color)); 29 | vertices.Append(new Vertex(point1 - offset, color)); 30 | } 31 | 32 | public void Draw(RenderTarget target, RenderStates states) 33 | { 34 | target.Draw(vertices, states); 35 | } 36 | } 37 | } 38 | --------------------------------------------------------------------------------