Jump to content
  • Advertisement
  • entries
    31
  • comments
    29
  • views
    5554

About this blog

I want to explain my progress of game development in the form of step-by-step instructions for beginners.

Entries in this blog

Texture Movement. WebGL, TypeScript

I made a simple example with checking of collision with right wall: Plunker: https://next.plnkr.co/edit/Bgf18uHzIkrRw9oW?preview CodeSandbox: https://codesandbox.io/s/texture-movement-webgl-10-typescript-3v8c6 GitHub + Build Instruction: https://github.com/8Observer8/texture-movement_webgl10-typescript private GameLoop(): void { this.Update(); this.Draw(); requestAnimationFrame(() => this.GameLoop()); } private Update(): void { this._x += 2; // Check a collisiion with the right wall if (this._x > this._gl.canvas.width) { // Move an object to left wall this._x = 0; } mat4.identity(this._modelMatrix); mat4.translate(this._modelMatrix, this._modelMatrix, vec3.fromValues(this._x, this._y, 0)); mat4.rotateZ(this._modelMatrix, this._modelMatrix, 0 * Math.PI / 180.0); mat4.scale(this._modelMatrix, this._modelMatrix, vec3.fromValues(32, 32, 1)); let uModelMatrix = this._gl.getUniformLocation(this._program, "uModelMatrix"); this._gl.uniformMatrix4fv(uModelMatrix, false, this._modelMatrix); } private Draw(): void { this._gl.clear(this._gl.COLOR_BUFFER_BIT); this._gl.drawArrays(this._gl.TRIANGLE_STRIP, 0, 4); }  

8Observer8

8Observer8

The shortest app in WebGL and JS

Filling a canvas with set color. It is one of the shortest web application in WebGL 1.0 and JavaScript. It set a clear color and fill the canvas with the color. You can run this applications in Playground (in Plunker), watch demo, read code, make Fork, write something, send a link to your friends: https://next.plnkr.co/edit/nGfFeDfD9WbGs1aS?open=index.html&preview Plunker: https://next.plnkr.co/edit/nGfFeDfD9WbGs1aS?open=index.html&preview
CodePen: https://codepen.io/8Observer8/pen/VwwmxLd
JSFiddle: https://jsfiddle.net/8Observer8/akv6eh0o/
  <!DOCTYPE html> <html> <body> <canvas id="c" width="256" height="256"></canvas> <script> var canvas = document.getElementById('c'); var gl = canvas.getContext('webgl'); gl.clearColor(0.2, 0.5, 0.3, 1); gl.clear(gl.COLOR_BUFFER_BIT); </script> </body> </html>  

8Observer8

8Observer8

Textured Rectangle. WebGL 1.0, TypeScript

Textured Rectangle in pure WebGL 1.0 and TypeScript. I use glMatrix for Linear Algebra. Playground: Plunker: https://next.plnkr.co/edit/4pnm93F1eWQuvpYg?preview CodeSandbox: https://codesandbox.io/s/textured-rectangle-with-transforms-typescript-s7gfb

8Observer8

8Observer8

 

WebGL example for beginners in computer graphics

It is my example how to draw a triangle using WebGL and TypeScript: https://plnkr.co/edit/PkqSZGwhv9zKSnUNSiXo?p=preview Just fork my example, change it, save and send a new link to your friends. I use glMatrix library for math. You can find in the ShaderProgram.ts file hwo I set scale, rotation, and translation:         let modelMatrix = mat4.create();         mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(0, 0.5, 0));         mat4.rotateZ(modelMatrix, modelMatrix, 20.0 * Math.PI / 180.0);         mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(0.5, 0.5, 1));                  let u_ModelMatrix = gl.getUniformLocation(this.program, "u_ModelMatrix");         gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
 

8Observer8

8Observer8

C# GUI WPF + OpenGL 3.1

We will see how to place OpenTK.GLControl on WPF window to make GUI application with 2D/3D graphics using modern OpenGL 3. This is the result VS project: EditedTriangle_WPFOpenGL31CSharp.zip How to create the project from scratch Note 1: RMB - Right Mouse Button click
Note 2: Good Color calculator for normalized values: http://doc.instantreality.org/tools/color_calculator/ Create WPF application, with the name "EditedTriangle". See the screenshot: Download OpenTK.GLControl.zip and OpenTK.zip Create the empty "Libs" folder in the solution folder (where the ".sln" is placed) Unzip "OpenTK" and "OpenTK.GLControl" folder in the "Libs" folder Add references to "OpenTK.dll" and "OpenTK.GLControl.dll". For this: RMB on "References" -> select "Add Reference..." -> select "Browse" -> click the "Browse..." button -> select DLL's. See the screenshot with the result: Add "Assemblies". For this: select "Assemblies" -> "Framework" -> check: System.Drawing System.Windows.Forms WindowsFormsIntegration , see the screenshot with the result: Click "OK" button Open the file "MainWindow.xaml" in VS. Add this line as an attribute of the "Window" element: xmlns:opentk="clr-namespace:OpenTK;assembly=OpenTK.GLControl" Place this code inside of <Window></Window> element: <Grid> <DockPanel LastChildFill="True"> <StackPanel DockPanel.Dock="Right"> <Button x:Name="buttonSetBGColor" Content="Set BG Color" Margin="5" Click="buttonSetBGColor_Click"></Button> <Button x:Name="buttonSetTRColor" Content="Set TR Color" Margin="5" Click="buttonSetTRColor_Click"></Button> </StackPanel> <WindowsFormsHost Margin="5" Initialized="WindowsFormsHost_Initialized"> <opentk:GLControl x:Name="glControl" Load="glControl_Load" Paint="glControl_Paint" /> </WindowsFormsHost> </DockPanel> </Grid> Copy the code below to "MainWindow.xaml.cs" and run the project MainWindow.xaml.cs using System; using System.Windows; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; namespace Triangle_OpenGL31WPF { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private Utils.ShaderProgram _program; private Matrix4 _projMatrix; private int _startIndex = 0; private int _amountOfVertices = 3; public MainWindow() { InitializeComponent(); } private void WindowsFormsHost_Initialized(object sender, EventArgs e) { glControl.MakeCurrent(); } private void glControl_Load(object sender, EventArgs e) { GL.ClearColor(new Color4(0.631f, 0.6f, 0.227f, 1f)); _program = new Utils.ShaderProgram( "Shaders/vShader.glsl", "Shaders/fShader.glsl"); if (_program.Id == -1) { MessageBox.Show(string.Format("Error: see the file \"{0}\"", Utils.Logger.logFileName)); return; } InitVertexBuffers(); SetTriangleColor(Color4.Red); int uProjMatrix = GL.GetUniformLocation(_program.Id, "uProjMatrix"); if (uProjMatrix < 0) { Utils.Logger.Append("Failed to get uProjMatrix location"); return; } _projMatrix = Matrix4.CreateOrthographicOffCenter(-1f, 1f, -1f, 1f, 1f, -1f); GL.UniformMatrix4(uProjMatrix, false, ref _projMatrix); } private void InitVertexBuffers() { float[] vertices = new float[] { // Triangle 0.0f, 0.5f, // (x, y) -0.5f, -0.5f, 0.5f, -0.5f }; // Create a vertex buffer object int vbo; GL.GenBuffers(1, out vbo); // Bind the VBO to target GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); // Write the data into the VBO GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw); // Get the storage location of the aPosition int aPosition = GL.GetAttribLocation(_program.Id, "aPosition"); if (aPosition < 0) { Utils.Logger.Append("Failed to get the storage location of the aPosition"); return; } // Assign the VBO to aPosition variable GL.VertexAttribPointer(aPosition, 2, VertexAttribPointerType.Float, false, 0, 0); // Enable the assignment GL.EnableVertexAttribArray(aPosition); } private void glControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { GL.Viewport(0, 0, glControl.Width, glControl.Height); // Fill a canvas GL.Clear(ClearBufferMask.ColorBufferBit); if (_amountOfVertices > 0) { GL.DrawArrays(PrimitiveType.TriangleStrip, _startIndex, _amountOfVertices); } // Swap the front and back buffers glControl.SwapBuffers(); } private void buttonSetBGColor_Click(object sender, RoutedEventArgs e) { var dialog = new System.Windows.Forms.ColorDialog(); if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { float r = dialog.Color.R / 255f; float g = dialog.Color.G / 255f; float b = dialog.Color.B / 255f; GL.ClearColor(new Color4(r, g, b, 1f)); glControl.Invalidate(); } } private void buttonSetTRColor_Click(object sender, RoutedEventArgs e) { var dialog = new System.Windows.Forms.ColorDialog(); if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { float r = dialog.Color.R / 255f; float g = dialog.Color.G / 255f; float b = dialog.Color.B / 255f; SetTriangleColor(new Color4(r, g, b, 1f)); glControl.Invalidate(); } } private void SetTriangleColor(Color4 color) { int uTriangleColor = GL.GetUniformLocation(_program.Id, "uTriangleColor"); if (uTriangleColor < 0) { Utils.Logger.Append("Failed to get uTriangleColor location"); return; } Vector3 c = new Vector3(color.R, color.G, color.B); GL.Uniform3(uTriangleColor, ref c); } } } MainWindow.xaml <Window x:Class="Triangle_OpenGL31WPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Triangle_OpenGL31WPF" xmlns:opentk="clr-namespace:OpenTK;assembly=OpenTK.GLControl" mc:Ignorable="d" Title="Triangle" Height="256" Width="290"> <Grid> <DockPanel LastChildFill="True"> <StackPanel DockPanel.Dock="Right"> <Button x:Name="buttonSetBGColor" Content="Set BG Color" Margin="5" Click="buttonSetBGColor_Click"></Button> <Button x:Name="buttonSetTRColor" Content="Set TR Color" Margin="5" Click="buttonSetTRColor_Click"></Button> </StackPanel> <WindowsFormsHost Margin="5" Initialized="WindowsFormsHost_Initialized"> <opentk:GLControl x:Name="glControl" Load="glControl_Load" Paint="glControl_Paint" /> </WindowsFormsHost> </DockPanel> </Grid> </Window>  

8Observer8

8Observer8

 

GameDev Books

Updated 3/27/2019 I created a new section: Math and Physics I added a new link on this nice book: Beginning Math and Physics for Game Programmers I study how to write my own game engines using modern OpenGL/C# and WebGL/TypeScript. I advice you this book: C# Game Programming: For Serious Game Creation. This book shows how to write your own game engine with maintainable code using TDD. This is a great book. It is not for GameDev only. It shows how to develop big projects in general. I know that you like to write games using Game Engines like Unity. By this book you will know basics of Linear Algebra, Shader Math, Game Physics and so on. Shader Math is important for Unity too because you need to write shaders for Unity. HLSL and GLSL are very similar. It is a great book really. Behaviour-Driven Development: 2014 - 10 - BDD in Action: Behavior-driven development for the whole software lifecycle - John Ferguson Smart. Source Code: https://www.manning.com/books/bdd-in-action Test-Driven Development: 2013 - 12 - The Art of Unit Testing: with examples in C# - 2nd Edition - Roy Osherove. Source Code: https://github.com/royosherove/aout2 Writing Games: 2010 - 06 - C# Game Programming: For Serious Game Creation. Source Code: 9781435455566.zip (121 MB) 2015 - 09 - Build your own 2D Game Engine and Create Great Web Games Using HTML5, JavaScript, and WebGL by Kelvin Sung, Jebediah Pavleas, Fernando Arnez, and Jason Pace. Source Code: https://github.com/apress/build-your-own-2d-game-engine 2017 - 10 - Pro HTML5 Games - 2nd Edition - A.R. Shankar. Source Code: https://github.com/apress/pro-html5-games-17 2018 - 04 - Unity in Action - 2nd Edition - J. Hocking. Source Code: https://www.manning.com/books/unity-in-action-second-edition Computer graphics: 2013 - 07 - WebGL Programming Guide - K. Matsuda, R. Lea. Source Code: https://sites.google.com/site/webglbook/ 2013 - 06 - Computer Graphics Principles and Practice - 3rd Edition - John F. Hughes, Andries van Dam, Morgan McGuire, David F. Sklar, James D. Foley, Steven K. Feiner, Kurt Akeley. Source Code: http://cgpp.net/about.xml Math and Physics: 2004 - 04 - Beginning Math and Physics for Game Programmers - Wendy Stahler 2011 - 06 - Mathematics for 3D Game Programming and Computer Graphics - 3rd edition - Eric Lengyel 2011 - 11 - 3D Math Primer for Graphics and Game Development - F. Dunn, I. Parberry 2013 - 04 - Physics for Game Developers - 2nd Edition - David M. Bourg, Bryan Bywalec 2014 - 05 - Physics for JavaScript Games, Animation, and Simulations - Adrian Dobre, Dev Ramtal Multiplayer: 2015 - 05 - Multiplayer Game Development with HTML5 - Rodrigo Silveira. Source Code: https://www.packtpub.com/code_download/21527 2015 - 10 - Multiplayer Game Programming - &nbsp;Josh Glazer, Sanjay Madhav. Source Code: https://github.com/MultiplayerBook/MultiplayerBook

8Observer8

8Observer8

Javascript Specs for Node.js Calculator. Jasmine JS5

Let's write an executable documentation for server side calculator. Specifications: "Add(a, b)" method must to sum positive numbers. Specification name: Add_SumPositiveNumbers_ReturnsSum "Sub(a, b)" method must to subtract positive numbers. Specification name: Sub_SubtractPositiveNumbers_ReturnsSub Instruction: Create the "calculator-nodejs-jasmine-es5" folder Run these commands to install Jasmine locally: npm init -y npm install --save-dev jasmine Create the "jasmine.json" file in the "calculator-nodejs-jasmine-es5" folder Copy the content for the "jasmine.json" file from the link: https://jasmine.github.io/setup/nodejs.html and make some changes, see the content below: jasmine.json {     "spec_dir": "src_specs",     "spec_files": [         "**/*_tests.js",         "!**/*nospec.js"     ],     "random": false } Open the "package.json" file and add the command to run tests:     "scripts": {         "test": "node node_modules/jasmine/bin/jasmine.js  --config=jasmine.json"     }, Try to run tests. Enter the command:
  npm test You will see a message that "No specs found" Create the "src_shared" folder. Create the "calculator.js" file the the "src_shared" folder Create the "src_specs" folder. Create the "calculator_tests.js" file the the "src_specs" folder Add our specs described above to the "calculator_tests.js" file: calculator_tests.js var Calculator = require("../src_shared/calculator"); describe("Calculator", function() {     it("Add_SumPositiveNumbers_ReturnsSum", function()     {         // Arrange         var calculator = new Calculator();         var a = 5;         var b = 2;         var expectedSum = 7;           // Act         var actualSum = calculator.Add(a, b);           // Assert         expect(actualSum).toEqual(expectedSum);     });       it("Sub_SubtractPositiveNumbers_ReturnsSub", function()     {         // Arrange         var calculator = new Calculator();         var a = 5;         var b = 2;         var expectedSub = 3;           // Act         var actualSub = calculator.Sub(a, b);           // Assert         expect(actualSub).toEqual(expectedSub);     }); }); If you will run tests using the command "npm test" then you will see the message: Let's implement these methods and run tests using the command "npm test". You will see that the tests are passed.

calculator.js var Calculator = function() {   };   Calculator.prototype.Add = function(a, b) {     return a + b; };   Calculator.prototype.Sub = function(a, b) {     return a - b; }; module.exports = Calculator;  

8Observer8

8Observer8

C++ Text. Legacy OpenGL 1.5, FreeGLUT

What if you need to draw text with simple graphics? For example, you have a task in your college to draw plots with some text using C++. You can still use deprecated/legacy OpenGL 1.1 and FreeGLUT. This example shows how to draw a text using FreeGLUT and deprecated/legacy OpenGL 1.5. And this example shows how to set up FreeGLUT in Visual Studio 2015. Text_FreeGlutOpenGL15Cpp.zip - Just download and run this solution in your version of Visual Studio.  But do not forget to set "Platform Toolset" to "Your Version Of VS" in the project settings. See screenshot: If you want to set up FreeGLUT from scratch then download the "Libs" folders and set settings by yourself: Libs: Libs_FreeGlutOpenGL15.zip Settings: main.cpp

8Observer8

8Observer8

C++ y = Sin(x). Legacy OpenGL 1.1, FreeGLUT

VS2015: Sin_FreeGlutOpenGL11Cpp.zip (Everything has been set up already. Just download, select your version of VS in "General/Platform Toolset" in the project settings and run) Release: Sin_x86_EXE.zip Tools: Visual Studio 2015 "Win32 Console Application" FreeGLUT deprecated/legacy OpenGL 1.1 (docs: https://docs.microsoft.com/en-us/windows/desktop/opengl/opengl) Settings main.cpp  

8Observer8

8Observer8

 

Flowchart for Empty GLFW Window

This example just create a window and clear a canvas with color. Tools: VS2015, GLFW, OpenGL, C++. All libraries are included in the project. You can just download and run it. But you need to set your Visual Studio version in the project settings, Platform Toolset, see the screenshot below: Visual Studio Project: EmptyWindow_GlfwOpenGL31Cpp.zip main.cpp DRAKON-flowchart Sandbox If you do not know what is DRAKON-flowchart, you can watch this short video that I found in Youtube:  

8Observer8

8Observer8

 

C++ Set Up GTest for TDD. C++, VS

Before I will start I want to advise you to read this book: The Art of Unit Testing: with examples in C#. Yes, as you can see this book contains examples in C# but it is not important. This book contain very useful and important information how to write unit tests. I made an example of project in VS 2015: SortFunctions.zip  This project will show you how set up Google Test in Visual Studio and run simple unit tests. Note. If you have another version of VS then before you will run unit tests you need to select VS 2017, like in this screenshot: Google Test library is included in the project as source folder and it is placed in "Libs" folder. You need to: open the solution. The solution is file with name: "SortFunctions.sln" select your version of VS, for example VS 2017 instead of VS 2015 as in screenshot above make the "SortFunction_UnitTests" project as "StartUp Project". For this: make right mouse button click on the "SortFunction_UnitTests" project -> select "Set as StartUp Project" press Ctrl+F5 to run unit tests You will see this settings in the "SortFunction_UnitTests" project properties: $(SolutionDir)Libs\gtest-1.8.1\include $(SolutionDir)Libs\gtest-1.8.1 $(SolutionDir)SortFunction This solution include two projects: SortFunctions - this project contains modules that we want to test. For example, bubbleSort() method SortFunctions_UnitTests - this project contains unit tests Add existing files to the "SortFunctions_UnitTests" project: YourSolutionDir/Libs/gtest-1.8.1/src/gtest-all.cc YourSolutionDir/SortFunctions/SortFunctions.cpp The "SortFunctions" project has two files: SortFunctions.h #pragma once extern void bubbleSort(int *array, unsigned int amount); extern void countingSort(int *array, unsigned int amount); SortFunctions.cpp #include "SortFunctions.h" void bubbleSort(int *array, unsigned int amount) { } void countingSort(int *array, unsigned int amount) { } The "SortFunctions_UnitTests" project has tests. For example, this is the "bubbleSortTests.cpp" with two tests. The first test is for positive numbers and the second test is for negative numbers: bubbleSortTests.cpp #include <gtest/gtest.h> #include "SortFunctions.h" TEST(bubbleSortTest, AllPositiveElements) { // Arrange const unsigned int amount = 5; int actualArray[amount] = { 5, 3, 10, 2, 7 }; int expectedArray[amount] = { 2, 3, 5, 7, 10 }; // Act bubbleSort(actualArray, amount); // Assert for (size_t i = 0; i < amount; i++) { ASSERT_EQ(expectedArray[i], actualArray[i]); } } TEST(bubbleSortTest, AllNegativeElements) { // Arrange const unsigned int amount = 5; int actualArray[amount] = { -5, -3, -10, -2, -7 }; int expectedArray[amount] = { -10, -7, -5, -3, -2 }; // Act bubbleSort(actualArray, amount); // Assert for (size_t i = 0; i < amount; i++) { ASSERT_EQ(expectedArray[i], actualArray[i]); } } main.cpp #include <gtest/gtest.h> int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }  

8Observer8

8Observer8

Algorithm TDD and Simple Game Math

In this Blog Entry I will translate examples from the tutorial Math for Game Developers from C++ to C# and TypeScript. I will add unit tests to the examples. I use: NUnit and NSubstitute for C# Jasmine for TypeScript C# and TypeScript are very similar. TS has: properties and generics. TS has keywords like C#: interface, abstract (for classes and methods). Author of C# and TS is Anders Hejlsberg 001. Character Movement (Points and Vectors) TypeScript TypeScript Demo: Click to run the example in Sandbox TypeScript Source Code: 001_PointsAndVectors C# C# Source Code: 001_PointsAndVectors  

8Observer8

8Observer8

 

BabylonJS. Usage TS in Browser

If you what to use a few TypeScript files the Browser you need to bundle them in on file. What is simple and cheap way to make it? Use Browserify + UglifyJS tools. BabylonJS is a game engine for creating 3D browser games. BJS was written in TypeScript. I this instruction I will show you how to create an example with a few TypeScript files. I do not like use: Webpack, Gulp, Grunt and so on at the beginning for simple examples. Because they require a lot of disk space on my laptop for my little examples. I create a lot of examples when I study something. For example, Gulp requires 80 MB. If I have 100 examples in TS then I will lost 800 MB. I use Browserify for creating a bundle that I can use in the browser. And I use UglifyJS to minify this bundle. You can install them only once using this commands: npm install browserify -g npm install uglify-js -g Generate the “package.json” file using this command: npm init -y For example, you have two files with names “Program.ts” and “Game.ts” in the "src" folder. Open the “package.json” file and add these lines in the “scripts” section: "scripts": { "browserify": "browserify dist/Program.js -o dist/bundle.js", "uglifyjs": "uglifyjs dist/bundle.js -o dist/bundle.min.js", "build": "tsc && npm run browserify && npm run uglifyjs" }, You can generate the “bundle.min.js” in the "dist" folder later using this command: npm run build You can read here in the documentation: https://doc.babylonjs.com/ this information: I want to keep all “.d.ts” files in the separate folder with the name “typings”. Create a "tsconfig.json" file in your root folder and add this line of code to the “tsconfig.json” folder: "types": [ "./typings/babylon" ] You need to add two “script” tags to the “index.html”: <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="dist/bundle.min.js"></script> I will show the “Program.ts” file. Another part of the example you will find here: https://doc.babylonjs.com/ Scroll down and click on the "TypeScript" button. Source code: official-example-bjs-ts.zip Program.ts import { Game } from "./Game"; class Program { public static Main() { // Create the game using the 'renderCanvas'. let game = new Game('renderCanvas'); // Create the scene. game.createScene(); // Start render loop. game.doRender(); } } window.onload = () => { Program.Main(); }  

8Observer8

8Observer8

C# Update ProjMatrix. OpenGL 3.1, C#

This example show how to update projection matrix: Blackjack_WinFormsOpenGL31CSharp_UpdateProjMatrix.zip private void glControl_Resize(object sender, EventArgs e) { UpdateProjMatrix(); } private void UpdateProjMatrix() { float aspect = (float)glControl.Width / glControl.Height; float worldWidth = aspect * _worldHeight; // Define the project matrix Matrix4 projMatrix = Matrix4.CreateOrthographic(worldWidth, _worldHeight, 0.1f, 1000f); GL.UniformMatrix4(_uProjMatrixLoc, false, ref projMatrix); }

8Observer8

8Observer8

C# Textures. OpenTK, WinForms, C#

My example shows a simple way to draw a few textures using OpenGL 3.1 without writing you own engine like in previous instruction: BYO2DGE. 5.1 TextureShaders. C# Project for Visual Studio: Blackjack_WinFormsOpenGL31CSharp.zip You can use this example to start making card games.

8Observer8

8Observer8

C# BYO2DGE. 5.1 TextureShaders. C#

I study this book: Build your own 2D Game Engine. I rewrite the 2D game engine from the book from JavaScript to C#. I rewrote this example from the official book repository: 5.1.TextureShaders to C#: ColoredAndTexturedObjects_OpenTKOpenGL31CSharp.zip This example draw texture and color objects at the same time. You can move a tank by arrow keys and by WASD keys.

8Observer8

8Observer8

Javascript Specs for Calculator. Jasmine, JS5

Specifications: "Add(a, b)" method must to sum positive numbers. Specification name: Add_SumPositiveNumbers_ReturnsSum "Sub(a, b)" method must to subtract positive numbers. Specification name: Sub_SubtractPositiveNumbers_ReturnsSub Source Code: https://github.com/8Observer8/calculator-jasmine-es5 Instruction: Create the "calculator-jasmine-es5" folder Search in the Internet: cdn jasmine Create the "SpecRunner.html file in the "calculator-jasmine-es5" folder and add links on files: <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>Jasmine Spec Runner v3.3.0</title>     <link rel="shortcut icon" type="image/png"         href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine_favicon.png">     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.css">     <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.js"></script>     <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine-html.min.js"></script>     <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/boot.min.js"></script>     <!-- include source files here... -->     <script src="src_client/calculator.js"></script>     <!-- include spec files here... -->     <script src="src_specs/calculator_tests.js"></script> </head> </html> Note. Files "calculator_tests.js" was not created yet but we added links on them above. Create the "src_client" folder. Create the "calculator.js" file the the "src_client" folder Create the "src_specs" folder. Create the "calculator_tests.js" file the the "src_specs" folder Add our specs described above to the "calculator_tests.js" file: calculator_tests.js describe("Calculator", function() {     it("Add_SumPositiveNumbers_ReturnsSum", function()     {         // Arrange         var calculator = new Calculator();         var a = 5;         var b = 2;         var expectedSum = 7;         // Act         var actualSum = calculator.Add(a, b);         // Assert         expect(actualSum).toEqual(expectedSum);     });     it("Sub_SubtractPositiveNumbers_ReturnsSub", function()     {         // Arrange         var calculator = new Calculator();         var a = 5;         var b = 2;         var expectedSub = 3;         // Act         var actualSub = calculator.Sub(a, b);         // Assert         expect(actualSub).toEqual(expectedSub);     }); }); Open the "SpecRunner.html" in a browser to run tests. You will see errors in the browser because we did not implement the methods: Add(a, b) and Sub(a, b) Let's implement these methods and open the "SpecRunner.html" in the browser again to run tests. You will see that the tests are passed. calculator.js var Calculator = function() { }; Calculator.prototype.Add = function(a, b) {     return a + b; }; Calculator.prototype.Sub = function(a, b) {     return a - b; };  

8Observer8

8Observer8

Specs for Calculator. Jasmine, TS

In this instruction we will study how to write executable specifications for a very simple Calculator project using Jasmine testing framework. Source code on GitHub: https://github.com/8Observer8/calculator-browserify-ts If you do not have "browserify" then install it globally using this command: npm install browserify -g Note. You can read about why we need "browserify" in this project in my instruction here: Browserify TypeScript Create the folder "calculator-browserify-ts" and install the necessary package: npm init -y npm i -D @types/jasmine Search in the Internet: jasmine cdn. Create the "SpecRunner.html" file and copy founded CDN links to it: SpecRunner.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Jasmine Spec Runner v3.3.0</title> <link rel="shortcut icon" type="image/png" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine_favicon.png"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine-html.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/boot.min.js"></script> <!-- include source files here... --> <script src="dist_client/bundle.js"></script> <!-- include spec files here... --> <script src="dist_specs/bundle.js"></script> </head> </html> Let's describe specifications for our calculator. The calculator will have four operations: Add(a, b) Sub(a, b) Mul(a, b) Div(a, b) If "b == 0" then method "Div" will throw an exception with the text: "Divided by zero". Create the "src_specs" folder. Create the "calculator_tests.ts" in the "src_specs" folder Create the "src_client" folder. Create the "calculator.ts" in the "src_client" folder Let's create the first specification in the "calculator_tests.ts": import { Calculator } from "../src_client/calculator"; describe("Calculator", () => { it("Add_PositiveNumbers_ReturnsSum", () => { // Arrange let a = 9; let b = 1; let expectedSum = 10; // Act let actualSum = Calculator.Add(a, b); // Assert expect(actualSum).toBe(expectedSum); }); }); We could try to compile it but we cannot because we do not have the "Calculator" class. Let's add it in the "src_client" folder: calculator.ts export class Calculator { public static Add(a: number, b: number): number { return a + b; } } Add the "tsconfig.specs.json" file in the root of your projects: "tsconfig.specs.json" { "compilerOptions": { "sourceMap": true, "outDir": "dist_specs" }, "include": [ "src_specs/calculator_tests.ts", "src_client/calculator.ts" ], "exclude": [ "node_modules", "src_client" ] } Now we can compile and browserify the specification. Enter two commands: tsc -p tsconfig.specs.json browserify dist_specs/src_client/calculator.js dist_specs/src_specs/calculator_tests.js -o dist_specs/bundle.js You can add these commands to the "package.json" file in the "scripts" section: "scripts": { "build_specs": "tsc -p tsconfig.specs.json", "bundle_specs": "browserify dist_specs/src_client/calculator.js dist_specs/src_specs/calculator_tests.js -o dist_specs/bundle.js", "test": "echo \"Error: no test specified\" && exit 1" And you can run these short commands: npm run build_specs npm run bundle_specs Open the "SpecRunner.html" in the browser and you will see that the specification will run. Try to add another specifications for: Sub, Mul, and Div methods. Later I will add specification for "Divide by zero" exception.

8Observer8

8Observer8

 

Browserify TypeScript

It is the most common problem for anyone who starts to study TS. They cannot include a few ".js" files after compilation to <script> tags in "index.html". It is very simple in JS. You have two files in JS and you can include them in "index.html": index.html <html> <head>     <script src="js/sayHello.js"></script>     <script src="js/main.js"></script> </head> </html> sayHello.js function sayHello(name) {     console.log("Hello, " + name); } main.js function main() {     sayHello("Ivan"); } window.onload = main; Output:
  But if you rewrite these files in TypeScript: sayHello.ts export function sayHello(name: string): void {     console.log("Hello, " + name); } main.ts import { sayHello } from './sayHello'; function main(): void {     sayHello("Ivan"); } window.onload = main; And if you compile them to JavaScript: tsc ts/main.ts ts/sayHello.ts --outDir "dist" You cannot just include this files in "index.html": <html> <head>     <script src="dist/sayHello.js"></script>     <script src="dist/main.js"></script> </head> </html> You will see this errors in the browser debug console: There are a few ways to solve this problem: You can concatenate all generated ".js" files in one bundle.js file using: Webpack, Gulp, Grund and so on. For example, see this official instruction: Gulp - TypeScript You can compile to AMD modules and use RequreJS to load them. For example, see my instruction: A few TypeScript files on Sandbox You can use Browserify to concatenate all generated ".js" files in one bundle.js file I will show you how to use Browserify. Install Browserify using this command: npm install browserify -g You can create bundle.js using this command: browserify dist/main.js dist/sayHello.js -o dist/bundle.js You will see "bundle.js" in the "dist" folder. Now you can include "bundle.js" in "index.html" using <script> tag: <html> <head>     <script src="dist/bundle.js"></script> </head> </html> Open "index.html" file in a browser and you will see "Hello, Ivan" in the browser debug console. Bonus. UglifyJS You can install uglifyjs: npm install uglify-js -g And compress your "bundle.js" to "bundle.min.js": uglifyjs dist/bundle.js -o dist/bundle.min.js Do not forget to change a script name from "bundle.js" to "bundle.min.js" in "index.html": index.html <html> <head>     <script src="dist/bundle.min.js"></script> </head> </html>  

8Observer8

8Observer8

 

A few TypeScript files on Sandbox

There is a few TypeScript files in our example. We want to place these scripts on Sandbox. This is the result on the Sandbox: click. Open the debug console in your browser to see the result: "Ctrl+Shift+J" in Chrome. You will see in the debug console this messages: Create these files on Sandbox: https://plnkr.co/edit/ Program.ts import { Rectangle } from "./Rectangle"; export class Program { public static Main(): void { // Create a rectangle let rectangle = new Rectangle(); // Draw the rectangle rectangle.Draw(); } } Program.Main(); Rectangle.ts export class Rectangle {     public x: number;     public y: number;     public constructor(x: number = 0, y: number = 0)     {         /* ... */         console.log("Rectangle was created");     }     public Draw(): void     {         /* ... */         console.log("Rectangle was drawn");     } } We need to compile these files to AMD. For this, create the "tsconfig.json" file on the Sandbox: tsconfig.json { "compilerOptions": { "module": "amd", "outDir": ".", "sourceMap": true }, "include": [ "*.ts" ], "exclude": [ "" ] } Create the RequereConfig.ts file on the Sandbox: RequireConfig.ts requirejs.config({ baseUrl: "." }); requirejs(["Program"], (Program) => { }); Add "require.min.js" in the "index.html" file: index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>A few TypeScript files on sandbox</title> <script data-main="RequireConfig" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script> </head> <body> <h3>See the console output. Press "Ctrl+Shiprt+J" in the Chrome browser.</h3> </body> </html> This is the result on the Sandbox: click. Open the debug console in your browser to see the result: "Ctrl+Shift+J" in Chrome. You will see in the debug console this messages:   P.S. If you need to work locally you need to run these commands: npm init -y npm i -D @types/requirejs P.S.S. Read this book to learn more about AMD and RequireJS: Mastering TypeScript - 2nd Edition - Nathan Rozentals

8Observer8

8Observer8

 

C++ Set Up GMock for TDD. C++, VS

If you need the example how to set up GTest without GMock you can see this example: Set Up GTest for TDD. C++, VS In this example: PersonService_GMockCpp.zip  we will see how to use Google Mock for creating mock objects and how to write a unit test for testing exceptions. I translated this example from the TypeScript tutorial: Using Jasmine Spies to Create Mocks and Simplify the Scope of Your Tests You can download and run the example. Google Test library is included in the project as source folder and it is placed in "Libs" folder. Note. If you have another version of VS then before you will run unit tests you need to select VS 2017, like in this screenshot: You need to: open the solution. The solution is file with name: "PersonService.sln" select your version of VS, for example VS 2017 instead of VS 2015 as in the screenshot above make the "PersonService.UnitTests" project as "StartUp Project". For this: make right mouse button click on the "PersonService.UnitTests" project -> select "Set as StartUp Project" press Ctrl+F5 to run unit tests How to set up GTest and GMock from scratch I use version 1.8.1 of GTest and GMock. You can download these libraries here: gtest-1.8.1.zip gmock-1.8.1.zip You need to create a new solution. Write some name for you solution and for your project, for example: PersonService (for the solution and for the project). Pay attention, you need to check "Create directory for solution" when you create a new solution and project. Note. RMB - Right Mouse Button click. You can set up the project from scratch like this: Create a new solution with the name "PersonService". Check "Create directory for solution". Write name "PersonService" for project. Set a new project as: empty console project, without the "precompiled headers". The "PersonService" project will be a project under test Copy and add these files to the "PersonService": IDataContext.h #pragma once #include "Person.h" class IDataContext { public: virtual ~IDataContext() {}; virtual void SavePerson(const Person &person) = 0; }; IPersonValidator.h #pragma once #include "Person.h" class IPersonValidator { public: virtual ~IPersonValidator() {}; virtual bool IsValid(const Person &person) = 0; }; Person.h #pragma once #include <string> class Person { public: int number; std::string name; }; PersonService.h #pragma once #include "Person.h" #include "IPersonValidator.h" #include "IDataContext.h" class PersonService { public: PersonService(IPersonValidator *validator, IDataContext *dataContext); void Save(const Person &person); private: IPersonValidator *_validator; IDataContext *_dataContext; }; PersonService.cpp #include "PersonService.h" PersonService::PersonService(IPersonValidator *validator, IDataContext *dataContext) { _validator = validator; _dataContext = dataContext; } void PersonService::Save(const Person &person) { if (_validator->IsValid(person)) { _dataContext->SavePerson(person); } else { throw std::runtime_error("Person is not valid"); } } Add a new project in your solution. For this: RMB on the solution name -> "Add" -> "New Project..." -> Set a name: "PersonService.UnitTests". You project must be: console, empty and without the "precompiled headers". The "PersonService.UnitTests" project will have unit tests for the "PersonService" project Create the "Libs" folder in your solution folder (where your ".sln" file is placed) Copy the "gtest-1.8.1" and the "gmock-1.8.1" folders to the "Libs" folder from these archives: gtest-1.8.1.zip, gmock-1.8.1.zip Open the project properties of the project "PersonService.UnitTests" (RMB on the project name and select "Properties") and add these lines to "C/C++" -> "General" -> "Additional Include Directories": $(SolutionDir)Libs\gtest-1.8.1\include $(SolutionDir)Libs\gtest-1.8.1 $(SolutionDir)Libs\gmock-1.8.1\include $(SolutionDir)Libs\gmock-1.8.1 $(SolutionDir)PersonService Click "Apply" and "OK" buttons Make "PersonService.UnitTests" as "StartUp Project". For this: RMB on the "PersonService.UnitTests" project -> select "Set as StartUp Project" Add as "Existing Item" this file: "Libs\gtest-1.8.1\src\gtest-all.cc" and "Libs\gmock-1.8.1\src\gmock-all.cc". For this: RMB on the "PersonService.UnitTests" project -> select "Add" -> "Existing Item..." -> choose these files: "Libs\gtest-1.8.1\src\gtest-all.cc" and "Libs\gmock-1.8.1\src\gmock-all.cc" Add as "Existing Item" the files that you will test. For example, in this case: "PersonService.cpp" from the "PersonService" project Copy and add these files to the "PersonService.UnitTests": main.cpp #include <gmock/gmock.h> #include <gtest/gtest.h> int main(int argc, char **argv) { testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } PersonServiceTests.cpp #include <gmock/gmock.h> #include <gtest/gtest.h> using ::testing::_; using ::testing::Return; #include "IDataContext.h" #include "IPersonValidator.h" #include "Person.h" #include "PersonService.h" class MockDataContext : public IDataContext { public: MOCK_METHOD1(SavePerson, void(const Person &person)); }; class MockPersonValidator : public IPersonValidator { public: MOCK_METHOD1(IsValid, bool(const Person &person)); }; TEST(PersonService, IsValid_ValidPerson_CallSavePerson) { MockDataContext dataContext; MockPersonValidator validator; PersonService service = PersonService(&validator, &dataContext); Person validPerson; EXPECT_CALL(validator, IsValid(_)) .WillOnce(Return(true)); EXPECT_CALL(dataContext, SavePerson(_)).Times(1); service.Save(validPerson); } TEST(PersonService, IsValid_NotValidPerson_ThrowException) { MockDataContext dataContext; MockPersonValidator validator; PersonService service = PersonService(&validator, &dataContext); Person validPerson; EXPECT_CALL(validator, IsValid(_)) .WillOnce(Return(false)); EXPECT_CALL(dataContext, SavePerson(_)).Times(0); //EXPECT_THROW({ // service.Save(validPerson); //}, std::runtime_error); try { service.Save(validPerson); FAIL() << "Exptected std::runtime_error"; } catch (std::runtime_error const & err) { EXPECT_EQ(err.what(), std::string("Person is not valid")); } catch (...) { FAIL() << "Exptected std::runtime_error"; } } Run the "PersonService.UnitTests" project by pressing on "Ctrl+F5" buttons You will see that you tests passed:

8Observer8

8Observer8

 

Python Set up OpenGL 3 for Python

You need to type commands in the console terminal (you need to run the console terminal as administrator): pip install GLFW pip install PyOpenGL pip install Pyrr pip install NumPy Pyrr - for trigonometry and linear algebra NumPy - for special arrays for OpenGL functions You will see how to use these libraries in video tutorial below. Now you are ready to create simple games in Python and OpenGL. See this video tutorial about basics of OpenGL. You can start from the second lesson: Modern OpenGL programming in Python - part 02 - creating a GLFW window After studying of this tutorial you can rewrite a prototype of the Snake 2D Tutorial: Python Snake Game from deprecated/legacy OpenGL 1 to modern OpenGL 3 and make it 3D with textures and lighting. And you will be able to load 3D models from Blender because the video tutorial above covers loading 3D models from Blender. How to create an empty window using GLFW: Copy the file below ("main.py") Place glfw3.dll (glfw3.dll.zip) with "main.py" Run the application. For this run the command in the console terminal: python main.py main.py import glfw def main(): # Initialize glfw if not glfw.init(): return window = glfw.create_window(800, 600, "My OpenGL Window", None, None) if not window: glfw.terminate() return glfw.make_context_current(window) while not glfw.window_should_close(window): glfw.poll_events() glfw.swap_buffers(window) glfw.terminate() if __name__ == "__main__": main()  

8Observer8

8Observer8

 

Javascript Deploying Game Server on Heroku

Heroku is a free hosting. Let's deploy the application from this instruction: Emit and Broadcast JSON You need to register on https://heroku.com/  and complete this official instruction: Getting Started on Heroku with Node.js Go here: https://dashboard.heroku.com/apps  and create a new application. For this you need to press "New" button in right top corner. Select "create new app". I created a new application with the name: red-game. In this case, my application will be available from this domain: https://red-game.herokuapp.com/  When you create your application at first time you will see this web page: Go to your work folder using the console terminal. You need to have the file "app.js" and "client" folder in your work folder. Indeside "client" folder you need  to have "index.html" from the instruction above. But we will change a few lines in "app.js". We will change a port number. Replace this line of code: var port = 8080; On this line: var port = process.env.PORT || 3000; Note. If you do not want to read the previous instruction you can just copy-past this files and install packages using this commands: app.js var express = require("express"); var app = express(); var server = require("http").Server(app); app.get("/", function(req, res) { res.sendFile(__dirname + "/client/index.html"); }); app.use("/client", express.static(__dirname + "/client")); var port = process.env.PORT || 3000; server.listen(port); console.log("Server started. Port = " + port); var io = require("socket.io")(server, {}); var shortid = require('shortid'); io.sockets.on("connection", function(socket) { var clientName = shortid.generate(); console.log("client was connected, name = " + clientName); socket.on("getMyName", function() { socket.emit("onGetMyName", { name: clientName }); }); socket.on("sendMyNameToAllClients", function() { socket.broadcast.emit("onSendMyNameToAllClients", { name: clientName }); console.log(clientName); }); }); index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script> <title>Multiplayer Snake</title> </head> <body> <button onclick="getMyName();">Get My Name</button> <button onclick="sendMyNameToAllClients();">Send my Name to all Clients</button> <script> var socket = io(); socket.emit("hello", { message: "hello from client!" }); socket.on("onGetMyName", function(data) { console.log("My Name: " + data.name); }); socket.on("onSendMyNameToAllClients", function(data) { console.log("Name of another client: " + data.name); }); function getMyName() { socket.emit("getMyName"); } function sendMyNameToAllClients() { socket.emit("sendMyNameToAllClients"); } </script> </body> </html> Add a new file: .gitignore (pay attention, "." is a part of the name) The file ".gitignore" should have this content: Add the start script command in package.json here: "scripts": { "start": "app.js", "test": "echo \"Error: no test specified\" && exit 1" }, Enter these commands in the command terminal. Pay attention: you need to write your application name instead of "red-game": Now we can to add new files, commit them and push/deploy our application on Heroku. Enter these commands: Go to your application in the browser. For example, in my case: https://red-game.herokuapp.com/ Open the browser console, for example in Chrome: "Ctrl+Shift+J". Click on buttons and you will see messages in the browser console. Open two tabs and press "Send my Name to all Clients" button. You will see a messages in the console in the second client tab. P.S. You need to empty cache when you change your client side scripts of files: RMB on "Reload" button and select "Empty Cache and Hard Reload"

8Observer8

8Observer8

C# GUI WinForms + OpenGL 3.1

This my example how to use GUI WinForms and OpenTK.GLControl Source for Visual Studio (including DLLs): EditedTriangle_WinFormsOpenGL31CSharp.zip EXE: EditedTrianlge_WinFormsOpenGL31CSharp_EXE.zip Separated DLL's for references: OpenTK.zip, OpenTK.GLControl.zip Standard WinForms Color Dialog:          

8Observer8

8Observer8

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!