<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Proclive]]></title><description><![CDATA[Games and applications development]]></description><link>https://proclive.io/</link><generator>Ghost 0.11</generator><lastBuildDate>Wed, 29 Apr 2026 12:09:25 GMT</lastBuildDate><atom:link href="https://proclive.io/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Building "Castle Wars: Legacy"]]></title><description><![CDATA[<p><strong>Castle Wars: Legacy</strong> started as a side project in late 2024. The original idea was simple: take the classic castle wars card game that a lot of us played as kids on old Flash game sites and rebuild it for the modern web. No downloads, no installs, just open a</p>]]></description><link>https://proclive.io/castle-wars-legacy/</link><guid isPermaLink="false">7e8abc6b-9dac-4417-98e0-851b3c7f293b</guid><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Tue, 31 Mar 2026 11:14:05 GMT</pubDate><content:encoded><![CDATA[<p><strong>Castle Wars: Legacy</strong> started as a side project in late 2024. The original idea was simple: take the classic castle wars card game that a lot of us played as kids on old Flash game sites and rebuild it for the modern web. No downloads, no installs, just open a browser and play.</p>

<p><img src="https://cwl.proclive.io/promo/cwl_promo_wizard.png" alt="Castle Wars: Legacy promo artwork"></p>

<p>The first version was rough. A basic game loop, two players taking turns playing cards, castles going up and coming down. It worked, but it felt lifeless. The cards were static, turns had no weight to them, and the whole thing looked like a prototype because it was one.</p>

<p><strong>The stack</strong></p>

<p>I went with Node.js and Express on the backend, with server-side rendered JSX templates and HTMX handling most of the interactivity. The real-time multiplayer runs over WebSockets. State lives in Valkey (a Redis fork) for persistence. It is not a typical setup for a game, but it works surprisingly well for a turn-based card game. Pages load fast, the server does the heavy lifting, and the client stays light.</p>

<p>No React, no Vue, no build step for the frontend. Just plain JSX templates rendered on the server and HTMX swapping in the updates. It sounds old-fashioned but it keeps things simple.
  When a player plays a card, the server calculates the new state, renders the HTML fragments, and pushes them to both players over the WebSocket. Both sides always see the same thing
  because there is only one source of truth.</p>

<p>Getting the game right</p>

<p>The card balance took a long time to get anywhere close to right. There are 57 cards in the game right now, split across offense, defense, magic, resource, and special types. Each one interacts with castle HP, wall height, and three resource pools (bricks, crystals, weapons). Early on, some cards were obviously broken. A well-timed Dragon could end games in three turns. Resource generation cards felt pointless when you could just rush offense. It took dozens of playtesting rounds and small tweaks to get the pacing where it should be.</p>

<p>The AI opponent went through several iterations too. The first version just picked random legal cards. Then it got some basic heuristics, like preferring offense when the opponent has low
   walls, or building walls when under pressure. It is not going to fool anyone into thinking they are playing a human, but it gives new players something to practice against and fills the
  gap when nobody else is online.</p>

<p>Campaign mode</p>

<p>Single player campaign was one of the bigger additions. Six levels, each with a different AI personality and modified deck. Some levels limit your resources, some give the AI a head
  start, one gives the AI a stacked deck of high-cost cards. The idea was to teach different strategies through the level design itself rather than through tutorials. There is a star rating
   system for each level based on how quickly you win, which gives people a reason to replay.</p>

<p>Going cross-platform</p>

<p>The game runs as a PWA, so you can install it on your phone or tablet and it works. It is also a Discord Activity now, so people can play directly inside Discord
   voice channels with friends. That was an interesting integration. Discord's Embedded App SDK handles the auth flow and lets you pull in the player's Discord identity, so their username
  shows up in-game automatically.</p>

<p>There is a Steam release in the works too. That one is an Electron wrapper that loads the web version but adds Steamworks SDK integration for achievements, cloud saves, and the Steam
  overlay. The game itself stays the same, just packaged differently.</p>

<p>Multiplayer and matchmaking</p>

<p>The matchmaking is intentionally simple. Click play, get put into an open room or create a new one. No queues, no ranked tiers, no wait times. For a small player base, anything more
  complicated would just mean longer waits. There is an ELO rating system running in the background that powers the leaderboards, but it does not gate who you can play against.</p>

<p>One thing I added recently is the ability to join games that are already in progress against AI. If someone is playing solo and you click play, you get a choice: jump in and replace the
  AI, or start a fresh room. Small feature, but it makes the game feel more alive when there are only a handful of players online.</p>

<p>Push notifications handle the asynchronous side. In long game mode, you can play a turn and close the browser. When your opponent plays, you get a notification to come back. It is not
  real-time at that point, more like correspondence chess but with castles.</p>

<p>Tournaments</p>

<p>The tournament system runs on a scheduled bracket format. Players sign up, get matched into a single-elimination bracket, and play through the rounds. Each match is a standard game with a
   time limit. The bracket updates live on a hex-grid map that shows which castles are still standing and which have fallen. It is probably the most over-engineered feature in the whole
  project, but it looks cool and gives the competitive players something to aim for.</p>

<p>What I learned</p>

<p>Building a multiplayer game on web tech taught me a lot about state management and the thousand ways things can go out of sync. WebSocket connections drop. Sessions expire. Players close
  their browser mid-turn and come back three days later expecting everything to still be there. Every edge case you can think of will happen, and a few you would never think of.</p>

<p>The HTMX approach turned out to be a good fit for this kind of game. Turns are discrete, state changes are well-defined, and the server already knows everything. There is no need for a
  thick client keeping its own copy of the game state. The trade-off is that you lose the ability to do complex client-side animations, but for a card game about building castles, simple
  transitions and CSS animations do the job.</p>

<p>If I were starting over, I would probably make the same tech choices. The simplicity of the stack means I spend most of my time on game features instead of fighting tooling. And for a
  solo project, that matters more than anything.</p>

<p>What is next</p>

<p><strong>Steam</strong> launch is the immediate goal. After that, more campaign levels, more eye candy, and some kind of clan or guild system tied into the Discord integration. The leaderboard already tracks
  which <strong>Discord</strong> servers have the most active players, so building on that with server-vs-server competitions is the natural next step.</p>

<p>The game is free to play at <a href="https://cwl.proclive.io">https://cwl.proclive.io</a> and as a Discord Activity. If you have any feedback or want to follow development, the in-game chat is usually the fastest way to reach me.</p>]]></content:encoded></item><item><title><![CDATA[Trooper is launched!]]></title><description><![CDATA[<p>The game we have been tirelessly working on for eons is finally finished. Okay, yeah, maybe not tirelessly... you know. Or working... or finished. But its out! There's a lot of optimization under way and long nights of exterminating bugs, implementing features and whatnot  but we are proud to present</p>]]></description><link>https://proclive.io/trooper-is-launched-into-orbiiiiit/</link><guid isPermaLink="false">a5dbd877-4471-46dd-a0d0-b91d195cd5b5</guid><dc:creator><![CDATA[Dinko Neuhold]]></dc:creator><pubDate>Mon, 12 Jun 2017 20:56:13 GMT</pubDate><content:encoded><![CDATA[<p>The game we have been tirelessly working on for eons is finally finished. Okay, yeah, maybe not tirelessly... you know. Or working... or finished. But its out! There's a lot of optimization under way and long nights of exterminating bugs, implementing features and whatnot  but we are proud to present (in any version you might have stumbled upon)...</p>

<h1 id="trooper">Trooper</h1>

<p><a href="http://trooper.life"> <br>
<img alt="trooper_launched" src="http://i.imgur.com/nwIZbnQ.jpg" <br="">
</a>Packed with dodging <strong>bullets</strong> there are <em>ninjas</em> coming out of walls, constant rain of plasma in the arena and surprising frags even Nostradamus didn't see coming! Check it out we even got featured by iHASYOU and it hasn't even been a week!  </p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/E2nmNl7OeA8" frameborder="0" allowfullscreen></iframe>

<h5 id="wealsolaunchedapatreonsite">We also launched a patreon site</h5>

<p>You can support us there with about three fiddy a month so one day we might even shed the weight of creative chains that is ad-based revenue. We will put more updates there as well so you can do some corporate spying of our team, our process, and our awesome ideas (again, for about three fiddy). <br>
<a href="https://www.patreon.com/proclivetrooper"><img src="https://c4.patreon.com/toolbox/patreon_black.png" alt="Foo" title=""></a></p>]]></content:encoded></item><item><title><![CDATA[Featured on Likemindedd]]></title><description><![CDATA[<p>We gave a short interview to Likemindedd. They are writing short stories about game development teams, you can read a bit more about us here: <br>
<a href="https://likemindedd.wordpress.com/category/game-dev-stories/">Game Dev Stories</a></p>]]></description><link>https://proclive.io/featured-by-likemindedd/</link><guid isPermaLink="false">ac9925a4-9435-4474-8886-c43721054ab6</guid><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Sat, 06 May 2017 18:34:21 GMT</pubDate><content:encoded><![CDATA[<p>We gave a short interview to Likemindedd. They are writing short stories about game development teams, you can read a bit more about us here: <br>
<a href="https://likemindedd.wordpress.com/category/game-dev-stories/">Game Dev Stories</a></p>]]></content:encoded></item><item><title><![CDATA[Lights in pixi.js]]></title><description><![CDATA[<p>Now this is one problematic topic...</p>

<p>As of writing this article PIXI.js version is 4.5.1 and lights are still not a part of official release, but if you really really want to have lights in your pixi project, there is a way. <br>
All thanks to a guy</p>]]></description><link>https://proclive.io/lights-in-pixi-js/</link><guid isPermaLink="false">be7c6210-a4c2-4786-bf2c-584015fc81cc</guid><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Thu, 27 Apr 2017 12:58:36 GMT</pubDate><content:encoded><![CDATA[<p>Now this is one problematic topic...</p>

<p>As of writing this article PIXI.js version is 4.5.1 and lights are still not a part of official release, but if you really really want to have lights in your pixi project, there is a way. <br>
All thanks to a guy called finscn, I don't know much about him, but he'll be a hero of this article.</p>

<p>Anyway, let's get to the juicy part. You can grab his pixi version from <a href="https://github.com/finscn/pixi.js">here</a> but you'll probably have to build it yourself, or in case if lights get removed, I'll upload a pixi version which I have built from his repo, tested and wrote this article on so chances are it will most likely work if you download <a href="http://proclive.io/assets/downloads/finsc_pixi_v4.5.0.zip">this file</a>. Hopefully I'll update this version as new pixi versions get out, or feel free to remind me once in a while in the comments if necessary.</p>

<p>Before we start, here is what you're after:</p>

<iframe width="512" height="560" src="https://proclive.io/assets/tutorials/lightsAgain/main.html" frameborder="0" style="overflow:hidden" scrolling="no"></iframe>

<p>To make that, you'll need at least 2 images, a normal one and a normals map one, here are the two from the example, courtesy of Proclive artist Pjero Jericic:</p>

<p><img src="http://proclive.io/assets/tutorials/lightsAgain/image/alienByIggy.png" alt="">
<img src="http://proclive.io/assets/tutorials/lightsAgain/image/alienByIggy_NORMALS.png" alt=""></p>

<p>I've pushed this one a bit too far with settings for generating the normals image, pushed sharpness to the max and crazy stuff like that. This can probably look a lot better with more experimenting but I was just glad it worked and moved on.</p>

<p>Time to filter out people who came to copy/paste so here you go:</p>

<p>First, project structure.  </p>

<pre><code>image/  
image/bg.jpg  
image/bgNormals.jpg  
image/alien.png  
image/alienNormals.png  
lib/  
lib/pixi.js  
main.html  
main.js  
</code></pre>

<p>main.html  </p>

<pre><code class="language-html">&lt;!DOCTYPE html&gt;  
&lt;html&gt;  
    &lt;head&gt;
        &lt;meta charset="utf8" /&gt;
        &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
        &lt;meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" /&gt;

        &lt;title&gt;Pixi v4.5.0 Lights with finscn and proclive&lt;/title&gt;
        &lt;style&gt;
            html, body { margin:0; padding: 0 }
        &lt;/style&gt;
    &lt;/head&gt;

    &lt;body&gt;
        &lt;canvas id="canvas"&gt;&lt;/canvas&gt;
        &lt;script src="lib/pixi.min.js"&gt;&lt;/script&gt;
        &lt;script src="main.js"&gt;&lt;/script&gt;
        &lt;script&gt;

        &lt;/script&gt;
        &lt;br&gt;Number of Lights: &lt;span id="numLights"&gt;1&lt;/span&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>main.js  </p>

<pre><code class="language-javascript">var DirectionalLight = PIXI.lights.DirectionalLight;  
var PointLight = PIXI.lights.PointLight;


var canvas = document.getElementById("canvas");  
var viewWidth = 512;  
var viewHeight = 512;

var renderer = new PIXI.WebGLRenderer(viewWidth, viewHeight, {  
    view: canvas
});

var stage = new PIXI.Container();  
var lightCount = 1;


var lightHeight = 90;  
var allLights = [];


var dirLight = new DirectionalLight({  
    color: 0xffdd66,
    brightness: 0.25,
    ambientColor: 0x555555,
    ambientBrightness: 0.6,
    position: {
        x: 0,
        y: 0,
        z: lightHeight,
    },
    target: {
        x: 0,
        y: 0,
        z: 0,
    }
});

var mouseLight = new PointLight({  
    color: 0xffffff,
    brightness: 4,
    position: {
        x: viewWidth / 2,
        y: viewHeight / 2,
        z: lightHeight,
    }
});

allLights.push(dirLight);  
allLights.push(mouseLight);


function createClickLight(x, y) {  
    var clickLight = new PointLight({
        color: 0xee3311,
        brightness: 8,
        falloff: [0.3, 6, 60],
        position: {
            x: x,
            y: y,
            z: lightHeight,
        }
    });
    allLights.push(clickLight);
}

PIXI.loader  
    .add('alien_diffuse', 'image/alienpng')
    .add('alien_normal', 'image/alienNormals.png')
    .add('bg_diffuse', 'image/bg.jpg')
    .add('bg_normal', 'image/bgNormals.jpg')
    .load(function(loader, res) {
        var bg = new PIXI.Sprite(res.bg_diffuse.texture);
        stage.addChild(bg);

        var alien = new PIXI.Sprite(res.alien_diffuse.texture);

        alien.position.set(0, 0);
        alien.scale.set(0.5, 0.5);

        dirLight.target.x = alien.x;
        dirLight.target.y = alien.y;
        dirLight.updateDirection();

        bg.normalTexture = res.bg_normal.texture;
        alien.normalTexture = res.alien_normal.texture;

        bg.pluginName = "lightSprite";
        alien.pluginName = "lightSprite";

        bg.lights = allLights;
        alien.lights = allLights;

        stage.addChild(alien);

        canvas.addEventListener('mousemove', function(e) {
            var rect = e.target.getBoundingClientRect();

            mouseLight.position.x = e.clientX - rect.left;
            mouseLight.position.y = e.clientY - rect.top;
        });

        canvas.addEventListener('click', function(e) {
            var rect = e.target.getBoundingClientRect();

            createClickLight(e.clientX - rect.left, e.clientY - rect.top);

            document.getElementById('numLights').textContent = ++lightCount;
        });

        animate();
    });

function animate() {  
    requestAnimationFrame(animate);
    renderer.render(stage);
}
</code></pre>

<p>People who kept reading and didn't copy/paste directly into their working project parts of code which they thought they need will know that this only works with WebGLRenderer, apart from that, all you need to do when adding a new sprite is:</p>

<ul>
<li>add a new sprite created with diffuse image</li>
<li>set ".normalTexture" to normal map (name from loader.add first param)</li>
<li>set ".pluginName" to "lightSprite"</li>
<li>set ".lights" to array containing all lights that should affect that sprite</li>
</ul>

<p>Simple enough, now let's hope finscn PR gets merged into official pixi.js repo and get released soon so I can rewrite this tutorial.</p>

<p>That's all folks, now I can't wait to see some lights flickering on some game character using minigun</p>]]></content:encoded></item><item><title><![CDATA[Photoshop Frame Animation Tutorial]]></title><description><![CDATA[<p>Hello folks! In this tutorial I will show you how to create a character using frame animation in Photoshop CC 2015, but the steps should be similar in other versions.</p>

<p>Finished product <br>
<img src="https://proclive.io/content/images/2017/03/npc-demo.gif" alt=""></p>

<p>This is a npc character from our upcoming game Trooper, which will be a fun and cool 2D</p>]]></description><link>https://proclive.io/photoshop-frame-animation-tutorial/</link><guid isPermaLink="false">701ac0d3-ef33-4d49-80de-92414715a852</guid><category><![CDATA[photoshop]]></category><category><![CDATA[tutorial]]></category><category><![CDATA[frameanimation]]></category><category><![CDATA[gamedesign]]></category><category><![CDATA[character design]]></category><dc:creator><![CDATA[Pjero Jercic]]></dc:creator><pubDate>Thu, 16 Mar 2017 15:44:26 GMT</pubDate><content:encoded><![CDATA[<p>Hello folks! In this tutorial I will show you how to create a character using frame animation in Photoshop CC 2015, but the steps should be similar in other versions.</p>

<p>Finished product <br>
<img src="https://proclive.io/content/images/2017/03/npc-demo.gif" alt=""></p>

<p>This is a npc character from our upcoming game Trooper, which will be a fun and cool 2D shooter, with signature style and enemies. We are doing all of our animations in "frame by frame"(pretty awesome, right?). I chose this type of character for the tutorial because it only has two actions: "walking" and "idle". <strong>Let's break down all the steps and then you can watch the video at the bottom of this post</strong>.</p>

<p>Alright, let's get started!</p>

<p><strong>Step 1: Drawing</strong></p>

<p>Choose your character or draw something similar, whatever you like. Style and coloring is not important, be creative. <br>
Start with a sketch and try to visualize how your character will look and what parts will be animated. <br>
<img src="https://proclive.io/content/images/2017/03/sketch-1.png" alt="">
The most important thing is to draw all the body parts in different layers. In this case, we have a non playable character that doesn't have so much actions so I separated the head, body and legs(leg-front and leg-back). <br>
<img src="https://proclive.io/content/images/2017/03/body-and-head.png" alt="">
As you can see I have layers for the lineart(head, body, legf,legb) and colors(headx,bodyx,legfx and legbx) of each part of our soldier. <br>
<img src="https://proclive.io/content/images/2017/03/1111.png" alt="">
When I'm happy and satisfied with the finished look of my character I merge the matching layers and I create a group, in this case called "1". That will be the first frame for our animation. <br>
<img src="https://proclive.io/content/images/2017/03/group-layers.png" alt=""></p>

<p>Fun facts: <br>
Sometimes you can make things easier. I simply copied the front leg, reduced the size and there you go...now you have both legs. <br>
You can notice that my lineart for the head wasn't the same color as the rest of our soldier. I had to do some color blending for my "head" layer. Mistakes do happen but there is always a way to correct them as you go. :)</p>

<p><strong>Step 2: Animation</strong></p>

<p>After our soldier/character is all nice and ready we can start bringing him to life. I copied the group 3 more times so all together I have 4 same groups. I've done this many times so I kinda know up front that I will need 4 frames for walking. For each frame a matching group(frame  1=group 1,frame 2 =group 2,etc). You don't have to do things like this, you can just start with first one and copy it as you go. <br>
First open up the Timeline window. Go to the top navigation, choose Window > Timeline. The Timeline will let you turn on and off or move different layers for each frame. <br>
<img src="https://proclive.io/content/images/2017/03/timeline.png" alt="">
The Timeline window will appear at the bottom of your screen. In the Timeline window, click "Create Frame Animation". <br>
<img src="https://proclive.io/content/images/2017/03/cfa.png" alt="">
Your Timeline should look something like this. I have marked the important things that you can change/edit. <br>
<img src="https://proclive.io/content/images/2017/03/loop-options-.png" alt="">
For each frame you can choose which layers/groups will be visible or you can move different parts of our solider to create movement. For frame 1 you turn on just group 1, for frame 2 just group 2, etc. When you click on the first frame it will show that the group "1" is only visible. So you choose layer legf(front) and you move it as the character is walking. <br>
<img src="https://proclive.io/content/images/2017/03/Layer-1.png" alt="">
Repeat the process with other frames, try to experiment and play with the movement of the character as you like. <br>
<img src="https://proclive.io/content/images/2017/03/frame3.png" alt="">
This is the process of "walking". As you can see I'm moving his body and head a little because people do lean a bit when they are walking. Try to add small details like that. <br>
<img src="https://proclive.io/content/images/2017/03/lean-back.png" alt="">
For the "idle" process i just wanted to look like that the character is breathing. Of course, you have to create new frames and matching groups, in this case it was two new frames. I just moved "head" and "body" down a little for one frame to create movement. <br>
<img src="https://proclive.io/content/images/2017/03/idel.png" alt="">
You can always click "play" button at the bottom of the panel to see your animation and look for mistakes. Always remember, if you want to draw/add new things just create a new layer and copy it if you need it for more than one frame.</p>

<p><strong>Step 3: Exporting</strong></p>

<p>If you're happy with your animation and want to save it as a gif to use it online(or just brag about it to your friends), go to the top navigation bar and click File > Export > Save for Web (Legacy). <br>
<img src="https://proclive.io/content/images/2017/03/Layer-1-1.png" alt="">
If you want to export each layer cos you need them for sprite sheets(like we do in Proclive) the first thing to do is to merge your layers in each group and rename them as you wish. <br>
<img src="https://proclive.io/content/images/2017/03/Layer-2.png" alt="">
I had problems with exporting cos when I would select all the layers in the layer panel and then Right Click > Quick Export as PNG the Photoshop would trim the transparent pixels and the images won't be the same size. <br>
You can always click on File > Export > Quick Export as PNG but you will need to do that for each frame and it can take a lot of time when you have many frames. <br>
So, the best way to do this, go to the top navigation bar and click File > Export > Layers To files. I'm not sure if the older versions have this option but this is the easiest way to export your layers. <br>
<img src="https://proclive.io/content/images/2017/03/Unmark-this-.png" alt="">
After I export my layers I use <strong>TexturePacker</strong> to create sprite sheets. I know there are maybe some scripts for <br>
Photoshop but I find this program very easy to use.</p>

<p>I hope you guys liked this tutorial and enjoy the video.  </p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/xktdGHbohBU" frameborder="0" allowfullscreen></iframe>]]></content:encoded></item><item><title><![CDATA[Rotate towards mouse and shoot in that direction]]></title><description><![CDATA[A tutorial how to make a bunny shoot carrots out of a gun. With improvements for saving resources.]]></description><link>https://proclive.io/shooting-tutorial/</link><guid isPermaLink="false">4901d696-1c06-4248-aee9-458eee49c947</guid><category><![CDATA[PIXI]]></category><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Mon, 23 Jan 2017 19:02:22 GMT</pubDate><content:encoded><![CDATA[<p>Hello people, let's create a simple 2d shooter. And now as always, let's take care of copy/paste people by giving them what they want and move on :)</p>

<p>preview  </p>

<iframe width="800" height="600" src="https://proclive.io/assets/tutorials/shooter" frameborder="0" style="overflow:hidden" scrolling="no"></iframe>

<pre><code class="language-javascript">var renderer = PIXI.autoDetectRenderer(800, 600,{backgroundColor : 0x1099bb});  
document.body.appendChild(renderer.view);

// create the root of the scene graph
var stage = new PIXI.Container();

// create a texture from an image path
var texture = PIXI.Texture.fromImage('assets/bunny.png');  
var carrotTex = PIXI.Texture.fromImage('assets/carrot.png');

// create a new Sprite using the texture
var bunny = new PIXI.Sprite(texture);

// center the sprite's anchor point
bunny.anchor.x = 0.5;  
bunny.anchor.y = 0.5;

// move the sprite to the center of the screen
bunny.position.x = 200;  
bunny.position.y = 150;

var background = new PIXI.Graphics();  
background.beginFill(0x123456);  
background.drawRect(0,0,800,600);  
background.endFill();  
stage.addChild(background);

stage.addChild(bunny);

stage.interactive = true;

stage.on("mousedown", function(e){  
  shoot(bunny.rotation, {
    x: bunny.position.x+Math.cos(bunny.rotation)*20,
    y: bunny.position.y+Math.sin(bunny.rotation)*20
  });
})

var bullets = [];  
var bulletSpeed = 5;

function shoot(rotation, startPosition){  
  var bullet = new PIXI.Sprite(carrotTex);
  bullet.position.x = startPosition.x;
  bullet.position.y = startPosition.y;
  bullet.rotation = rotation;
  stage.addChild(bullet);
  bullets.push(bullet);
}

function rotateToPoint(mx, my, px, py){  
  var self = this;
  var dist_Y = my - py;
  var dist_X = mx - px;
  var angle = Math.atan2(dist_Y,dist_X);
  //var degrees = angle * 180/ Math.PI;
  return angle;
}

// start animating
animate();  
function animate() {  
  requestAnimationFrame(animate);

  // just for fun, let's rotate mr rabbit a little
  bunny.rotation = rotateToPoint(renderer.plugins.interaction.mouse.global.x, renderer.plugins.interaction.mouse.global.y, bunny.position.x, bunny.position.y);

  for(var b=bullets.length-1;b&gt;=0;b--){
    bullets[b].position.x += Math.cos(bullets[b].rotation)*bulletSpeed;
    bullets[b].position.y += Math.sin(bullets[b].rotation)*bulletSpeed;
  }
  // render the container
  renderer.render(stage);
}
</code></pre>

<p>To further improve this code, you should remove bullets when they hit something or get out of the screen. I use bullet manager class to recycle sprites instead of removing them and creating new ones. With any serious game you'll eventually want to avoid Garbage Collector calls and to save memory. You can also adjust functions to include distance from player and to add an offset to initial coordinates (like if you want to give a gun to the bunny), something like this:</p>

<pre><code class="language-javascript">{
  x: bunny.position.x+Math.cos(bunny.rotation)*distance+offset.x,
  y: bunny.position.y+Math.sin(bunny.rotation)*distance+offset.y
}
</code></pre>

<p>I'll have to make our illustrator Pjero draw a carrot gun so we can rotate that instead of the bunny but for quick and simple tutorial it will serve the purpose and push you in the right direction.</p>

<p>This tutorial can also be further improved with your suggestion so use that weird thing below this article in which you can write something so I can read it later.</p>]]></content:encoded></item><item><title><![CDATA[PIXI.js Drag and drop tutorial]]></title><description><![CDATA[Short and simple Drag and Drop PIXI.js tutorial. Cheers!]]></description><link>https://proclive.io/pixi-js-drag-drop/</link><guid isPermaLink="false">3bb4732f-61e1-4d1e-8a44-d2e67f56ddac</guid><category><![CDATA[PIXI]]></category><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Sun, 22 Jan 2017 18:22:06 GMT</pubDate><content:encoded><![CDATA[<p>Hello again, this one is a quicky, it's a Sunday and I had myself a beer so... short, simple and useful, here you go</p>

<pre><code class="language-javascript">var drag = false;  
createDragAndDropFor(container)

function createDragAndDropFor(target){  
  target.interactive = true;
  target.on("mousedown", function(e){
    drag = target;
  })
  target.on("mouseup", function(e){
    drag = false;
  })
  target.on("mousemove", function(e){
    if(drag){
      drag.position.x += e.data.originalEvent.movementX;
      drag.position.y += e.data.originalEvent.movementY;
    }
  })
}
</code></pre>

<p>Cheers!</p>]]></content:encoded></item><item><title><![CDATA[PIXI.js reverse mask]]></title><description><![CDATA[This is the first lesson and you're probably here to copy paste, see if it works and move on, so I'm going to try to make this as easy as possible for you..]]></description><link>https://proclive.io/pixi-js-reverse-mask-tutorial/</link><guid isPermaLink="false">9d120d26-4bd1-4472-8520-aaa159349652</guid><category><![CDATA[PIXI]]></category><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Sat, 21 Jan 2017 13:27:47 GMT</pubDate><media:content url="http://proclive.io/content/images/2017/01/tutorialWithDark-1.png" medium="image"/><content:encoded><![CDATA[<img src="http://proclive.io/content/images/2017/01/tutorialWithDark-1.png" alt="PIXI.js reverse mask"><p>It's time to start contributing back to the community so here's one tutorial on a subject I've noticed a lot of people get stuck on. I wanted to create a transparent gradient from center of the screen where it's clear to the edges where it's dark, like light effect. So here's a screenshot from a game we're currently developing before and after applying this effect.</p>

<p><img src="https://proclive.io/content/images/2017/01/tutorialWithoutDark.png" alt="PIXI.js reverse mask">
<img src="https://proclive.io/content/images/2017/01/tutorialWithDark.png" alt="PIXI.js reverse mask"></p>

<h1 id="tldr">TL;DR</h1>

<p>This is the first lesson and you're probably here to copy paste, see if it works and move on, so I'm going to try to make this as easy as possible for you. For a longer version scroll down.</p>

<pre><code class="language-javascript">/**
* @param size of the screen {width: 800, height: 800}
* @param renderer just pass the renderer
*/
var Light = function(size, renderer){  
  var self = this;
  self.size = size;
  self.renderer = renderer;

  self.container = new PIXI.Container();

  self.canvas = document.createElement('canvas');
  self.canvas.width = size.width;
  self.canvas.height = size.height;
  self.ctx = self.canvas.getContext('2d');

  self.renderTexture = PIXI.RenderTexture.create(self.size.width, self.size.height);
  self.maskSprite = new PIXI.Sprite(self.renderTexture);

  self.rendMask();

  self.darkTex = new PIXI.Texture.fromImage("assets/overlay2.jpg");
  self.darkSprite = new PIXI.Sprite(self.darkTex);
  self.darkSprite.filters = [new PIXI.SpriteMaskFilter(self.maskSprite)];
  self.container.addChild(self.darkSprite);
}

var pt = Light.prototype;

pt.rendMask = function(center, smallLights){  
  var self = this;

  if(!center){
    return false;
    center = {
      x: 400,
      y: 300
    }
  } else {
    center.x = center.x;
    center.y = center.y;
  }

  self.ctx = self.canvas.getContext('2d');

  self.ctx.clearRect(0,0,800,600);
  var gradient = self.ctx.createRadialGradient(center.x, center.y, 1, center.x, center.y, 600);
  gradient.addColorStop(0,"black");
  gradient.addColorStop(1,"white");
  self.ctx.fillStyle = gradient;
  self.ctx.fillRect(0,0,800,600);

  if(!self.spr){
    var texture = new PIXI.Texture.fromCanvas(self.canvas);
    self.spr = new PIXI.Sprite(texture);
  } else {
    self.spr.texture.update();
  }
  self.renderer.render(self.spr, self.renderTexture, true);
}

//module.exports = Light;
var light = new Light({width:800, height: 600}, renderer);

stage.addChild(light.container);  
</code></pre>

<p>and use in code like this:  </p>

<pre><code class="language-javascript">light.rendMask({x: renderer.plugins.interaction.mouse.global.x, y: renderer.plugins.interaction.mouse.global.y}, []);  
</code></pre>

<h1 id="initialsetup">Initial setup</h1>

<p>I'll try to make this as simple as possible so I'll use first basic example from pixi.js, i have this files and directory structure:  </p>

<pre><code>./
./assets/bunny.png
./assets/overlay2.jpg
./lib/pixi.js
./index.html
./main.js
</code></pre>

<p>here's index.html  </p>

<pre><code class="language-html">&lt;!DOCTYPE HTML&gt;  
&lt;html&gt;  
&lt;head&gt;  
     &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Proclive Tutorials: Light&lt;/title&gt;
    &lt;style&gt;
        body {
            margin: 0;
            padding: 0;
            background-color: #000000;
        }
    &lt;/style&gt;
    &lt;script src="lib/pixi.js"&gt;&lt;/script&gt;
&lt;/head&gt;  
&lt;body&gt;  
  &lt;script src="main.js"&gt;&lt;/script&gt;
&lt;/body&gt;  
&lt;/html&gt;  
</code></pre>

<p>main.js  </p>

<pre><code class="language-javascript">var renderer = PIXI.autoDetectRenderer(800, 600,{backgroundColor : 0x1099bb});  
document.body.appendChild(renderer.view);

// create the root of the scene graph
var stage = new PIXI.Container();

// create a texture from an image path
var texture = PIXI.Texture.fromImage('assets/bunny.png');

// create a new Sprite using the texture
var bunny = new PIXI.Sprite(texture);

// center the sprite's anchor point
bunny.anchor.x = 0.5;  
bunny.anchor.y = 0.5;

// move the sprite to the center of the screen
bunny.position.x = 200;  
bunny.position.y = 150;

stage.addChild(bunny);

// start animating
animate();  
function animate() {  
    requestAnimationFrame(animate);

    // just for fun, let's rotate mr rabbit a little
    bunny.rotation += 0.1;

    // render the container
    renderer.render(stage);
}
</code></pre>

<h1 id="funpart">Fun part</h1>

<p>Ok, time to put that bunny in the dark now. <br>
For my game i have used this image to add scratches on the screen, you don't need to use it if you want clear transitions. Your choice. Anyway, here's the image I'm using (it's .jpg, no transparency yet)</p>

<p><img src="https://proclive.io/content/images/2017/01/overlay2.jpg" alt="PIXI.js reverse mask"></p>

<p>and to make it work just append this code:</p>

<pre><code class="language-javascript">/**
* @param size of the screen {width: 800, height: 800}
* @param renderer just pass the renderer
*/
var Light = function(size, renderer){  
  var self = this;
  self.size = size;
  self.renderer = renderer;

  self.container = new PIXI.Container();

  self.canvas = document.createElement('canvas');
  self.canvas.width = size.width;
  self.canvas.height = size.height;
  self.ctx = self.canvas.getContext('2d');

  self.renderTexture = PIXI.RenderTexture.create(self.size.width, self.size.height);
  self.maskSprite = new PIXI.Sprite(self.renderTexture);

  self.rendMask();

  self.darkTex = new PIXI.Texture.fromImage("assets/overlay2.jpg");
  self.darkSprite = new PIXI.Sprite(self.darkTex);
  self.darkSprite.filters = [new PIXI.SpriteMaskFilter(self.maskSprite)];
  self.container.addChild(self.darkSprite);
}

var pt = Light.prototype;

pt.rendMask = function(center, smallLights){  
  var self = this;

  if(!center){
    return false;
    center = {
      x: 400,
      y: 300
    }
  } else {
    center.x = center.x;
    center.y = center.y;
  }

  self.ctx = self.canvas.getContext('2d');

  self.ctx.clearRect(0,0,800,600);
  var gradient = self.ctx.createRadialGradient(center.x, center.y, 1, center.x, center.y, 600);
  gradient.addColorStop(0,"black");
  gradient.addColorStop(1,"white");
  self.ctx.fillStyle = gradient;
  self.ctx.fillRect(0,0,800,600);

  if(!self.spr){
    var texture = new PIXI.Texture.fromCanvas(self.canvas);
    self.spr = new PIXI.Sprite(texture);
  } else {
    self.spr.texture.update();
  }
  self.renderer.render(self.spr, self.renderTexture, true);
}

//module.exports = Light;
var light = new Light({width:800, height: 600}, renderer);

stage.addChild(light.container);  
</code></pre>

<p>and modify animate() function to look like this:  </p>

<pre><code class="language-javascript">function animate() {  
    requestAnimationFrame(animate);

    // just for fun, let's rotate mr rabbit a little
    bunny.rotation += 0.1;
    if(light){
      light.rendMask({x: renderer.plugins.interaction.mouse.global.x, y: renderer.plugins.interaction.mouse.global.y}, []);
    }
    // render the container
    renderer.render(stage);
}
</code></pre>

<p>and the final (but simplified) product looks like this: <br>
(mouse over it to see it in action)</p>

<iframe width="800" height="600" src="https://proclive.io/assets/tutorials/light" frameborder="0" style="overflow:hidden" scrolling="no"></iframe>

<p>I had to strip my code down for the purpose of this tutorial, in original code i have implemented passing an array of small lights which i use for ambient and for glow on bullets. It's a bit more complicated in that case and it's CPU intensive but that can be fixed if you use smaller canvas size and scale it backup up to the screen size, in that case light is a bit pixelated but effective way to use in games without sacrificing too much resources for a single effect. If you're interested drop me a comment and I might write part II or expand this post to include it.</p>]]></content:encoded></item><item><title><![CDATA[Our first application]]></title><description><![CDATA[<p>We're proud to announce our first official application:</p>

<p><a href="http://tvseriestracker.com"><strong>TV Series Tracker</strong></a></p>

<p>Get notified of new episodes of your favorite TV series as they come out! </p>

<p>No need to install anything - TV Series Tracker will send you a Facebook notification when a new episode airs. You can check it out</p>]]></description><link>https://proclive.io/our-first-application/</link><guid isPermaLink="false">d61cfdc9-6bc5-4067-8a59-68c92acb036a</guid><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Wed, 07 Dec 2016 16:19:05 GMT</pubDate><content:encoded><![CDATA[<p>We're proud to announce our first official application:</p>

<p><a href="http://tvseriestracker.com"><strong>TV Series Tracker</strong></a></p>

<p>Get notified of new episodes of your favorite TV series as they come out! </p>

<p>No need to install anything - TV Series Tracker will send you a Facebook notification when a new episode airs. You can check it out <a href="http://tvseriestracker.com">here</a> for yourself, or see the video demonstration (0:45) below:</p>

<iframe width="480" height="270" src="https://www.youtube.com/embed/OUiph_tZS58" frameborder="0" allowfullscreen></iframe>]]></content:encoded></item><item><title><![CDATA[We're online!]]></title><description><![CDATA[<p>Stay tuned as we set up the workshop.</p>]]></description><link>https://proclive.io/were-online/</link><guid isPermaLink="false">aee0070f-7f49-4bb7-8bf3-87c43aaf0ab6</guid><dc:creator><![CDATA[Igor Neuhold]]></dc:creator><pubDate>Thu, 17 Nov 2016 12:10:16 GMT</pubDate><content:encoded><![CDATA[<p>Stay tuned as we set up the workshop.</p>]]></content:encoded></item></channel></rss>