Search

Geek Girl Joy

Artificial Intelligence, Simulations & Software

Tag

CSS

Mr Good Bot – Looking For Adventure

Today we implement a solution for the bug I mentioned last week and add a “Quick Say” feature to the admin interface.

Screenshot of the updated Mr. Good Bot Admin Interface
Screenshot of the updated Mr. Good Bot Admin Interface

Also, if you squint just right you might notice that the statement field changed to a text area element.

This is to make entering longer sentences more convenient because the element can be resized or stretched (drag the bottom right arrow) as needed.

Additionally, for your enjoyment, here is a higher resolution version of the featured image without the title text.

Mr Good Bot Looking For Adventure Wallpaper
Mr Good Bot Looking For Adventure Wallpaper

Here are the other posts in the Mr. Good Bot series:

Q&A

Q: What’s with the bot on a motorcycle?

A: It will make more sense after you read the code.

Q: I skipped ahead and read the code. So… you’re making some kind of overly obscure and hamfisted Steppenwolf reference?

A: Yeah… okay look it’s the end of the year and I have a lot of doings happening and the things, you know!? Like, what’s wrong with a Steppenwolf gag?

Q: Sure okay whatever, but then why not like, call it like… “Born To Be Wild”?

A: That’s silly! Bots are built not born. 😛

Plus that’s a bit of an obvious choice isn’t it?

Also, I’m all about trying not to get sued and Looking For Adventure seems less “infringy” while also being imbued with a positive child like imaginative sense of future.

Q: Fair enough, but… why isn’t Mr. Good Bot wearing a helmet? You realize that under California Vehicle Code 27803, Mr. Good Bot is required to wear a helmet and is clearly guilty of an infraction under the law?

A: Under most circumstances you are correct but you see, that law was clearly written to apply to endoskeletal citizens and Mr. Good Bot is an exoskeletal being so technically his head is a helmet and with “Jury nullification” being what it is… I’m sure no conviction would be forthright!

In any case, this interview is now over and all further inquiry should be directed towards Mr. Good Bot’s attorney!

A Bugged Bot

My little QA tester Xavier managed to find a couple of bugs in our prototype.

He found a way to get the bot into a state where it wouldn’t talk even if it had something to say and wasn’t speaking.

The bug seems to occur in two cases:

Continue reading “Mr Good Bot – Looking For Adventure”

Mr Good Bot – Administrative Speech Protocols Enabled

I’ve enabled the administrative speech protocols for Mr. Good bot allowing us to control his speech in real time outside of the database and I built out a nifty admin interface!

Screenshot of the Mr. Good Bot Admin Interface
Screenshot of the Mr. Good Bot Admin Interface

It works well enough but it makes a terrible wallpaper so here’s the featured image as a wallpaper:

Administrative Speech Protocols Enabled Wallpaper
Administrative Speech Protocols Enabled Wallpaper

And, for those of you who prefer more vibrant colors in their wallpapers, here’s the full color alternative (real 😉 ) version:

Administrative Speech Protocols Enabled Wallpaper Alternate
Administrative Speech Protocols Enabled Wallpaper Alternate

Now, if you’d like to know a little about how the admin system works and get the code (don’t worry it’s free), keep reading…

Continue reading “Mr Good Bot – Administrative Speech Protocols Enabled”

Mr Good Bot – Mostly Assembled

Mr. Good Bot is mostly assembled and we’re not looking at any code today (okay maybe just a little) but we’re really just going to talk about how Mr. Good Bot works and all the recent commits I made to Mr Good Bot over on GitHub.

Also, here’s the featured image from today’s post as a wallpaper. It depicts Mr. Good Bot being mostly assembled… I liked the look of hanging wires instead of legs, hence the name. 😛

Mr Good Bot Mostly Assembled Wallpaper
Mr Good Bot Mostly Assembled Wallpaper

If you need a refresher on this series, here are the other Mr. Good Bot posts:

 

So with Mr Good Bot being mostly assembled I thought we would take this opportunity to go over the recent additions.

Continue reading “Mr Good Bot – Mostly Assembled”

Mr Good Bot – Random Assembly Required

Today were going to look at assembling Frankenstein… I mean Mr. Good Bot.

By the end you will have the code needed to run Mr. Good Bot in his most basic capacity.

Before we proceed though, I caution all braves souls who dare venture further, this post will be frightfully technical and you need to be prepared for the coding horrors that lay ahead!

If your stomach turns at the sight of raw code (i.e. most sane folks) then I would suggest you keep right at the fork and head towards A Spooky Real Neat Blog Award for a more engaging and seasonally festive experience.

Though before you go, if you just want the featured image for this post, here’s the wallpaper

Random Assembly Required 1920 by 1080 Wallpaper
Random Assembly Required 1920 by 1080 Wallpaper

Otherwise, here are the other posts in this series if you need to catch up:

The Anatomy of a Good Bot

Mr. Good Bot uses HTML & CSS as the UI/Front End and a little JavaScript to request an updated image frame from the server.

This methodology allows for a simple implementation that I can make accessible on my air gaped home intranet to any authorized device with an IP Address and a browser.

Meaning Xavier can use a “smart device” (laptop, tablet, cellphone, watch, etc…) to keep his robot buddy with him while he’s running around playing.

It’s also possible to modify Mr. Good Bot slightly to accommodate multiple concurrent users.

Meaning Mr. Good Bot could even serve as my families own “smart home” digital assistant and we wouldn’t have to worry about unscrupulous 3rd parties monitoring everything we do or say!

All digital assist bots monitor you for “Learning & Quality Assurance”, look it up!

A Good Bot should be like a pet, a trusted and beloved family member, not a spy for BNN!

As it is (NOT A JOKE) Big Neural Network can and does monitor you at “their discretion”  through your “virtual assistant” with the stated intent at best “to sell you more shit” (paraphrasing)!

But… Let’s not turn this into another rant that gets me blacklisted again. 😛

In any case, because the interface is basically just a webpage Mr. Good Bot has access to all the functionality a web browser offers with the computation of a server, all over my LAN. 🙂

This opens up the possibility to do just about anything we want without relying on BNN tech.

Continue reading “Mr Good Bot – Random Assembly Required”

Mr Good Bot – Front-end

Welcome back for another episode of let’s build a bot! This week we’re building the front-end of Mr. Good Bot!

So look out the window and pick up every stitch because beatniks are out to make it rich!

Come, let the Bene Gesserit Reverend Mother Joy Muad’Dib guide you in the Weirding Way!

And… in case you missed it, those last couple sentence are an obscurish (but stupidly clever) way of joking that I’m a witch.

Like Donovan sang (paraphrasing)… “It must be the season of the October crone!”.

Yeah I know… its less funny if I explain it like that but I’d hate for the censorship bots to think I’m starting a cult.. okay, okay… another cult!

Look, I still contest it was valuable research alright!

Nonetheless, I don’t want to end up on the blacklist again, so… let’s just build the dang bot!

Mr. Good Bot’s Front-end

Sam (my research bot) and I went down into my bot dungeon… er… I mean “subterranean research facility” where we set about designing and constructing Mr. Good Bot for the amusement and bewilderment of all!

Design Considerations:

  • Any and all code should be short, simple and sweet… like me (that’s not true).
  • Everything should be easy for ANYONE, even illiterate people, to use and modify… wait, no… excuse me, that’s insensitive! What I meant to say is, people who can’t read and write code. 😛
  • Ideally Mr. Good Bot would be “skinable” to have more than one look and maybe even have the option to wear “accessories” because even though you never have the time, sometimes… accessories are fun!
  • Extra credit for cross-platform operation.
  • I’m juggling many irons in the fire ATM, so I should try to get the most effect for the least amount of effort on this project. Sort of a “Pareto’s principle of strategic half-assery”.

While discussing our options for rapid prototyping Mr. Good Bot, Sam and I made this list of methods we might use to animate the new bot:

Potential Animation Methods:

  • Still Frames.
  • Dynamic Layered SVG.
  • Pure HTML & JavaScript Canvas Animation.
  • A 3rd Party Animation Library.
  • Sacrificing a virgin… uh.. martini to summon an ancient automaton.

After careful consideration of all the factors Sam was frightfully dead-set on that last method because it involved his Bender Rodriguez impression!

Sam mentioned something about the possibility of meeting the great ToBoR “groking well” but the simulations he ran indicated the probability of success was inconclusive at best and likely low if positive.

So, I made Sam stop wasting my quality Spiced Melange Web Colors and we looked at our other options.

SVG

We decided against Dynamic Layered SVG’s because I have first hand knowledge that most technologically impaired geeks prefer raster over vector image creation.

As silly as that may seem at face value, I can understand why some feel that way.

Sometimes it really is just more fun to manipulate the squiggly colors as little quantized pixels of Joy rather than the product of markup or an equation!

Moving beyond the clearly undue self-aggrandizement for a moment, raster is a simpler and a more straightforward concept that many people already know and are comfortable with.

Also, using SVG would require that people use a very particular svg object naming convention that I would have to define and if you recall there is the critical half-assery constraint to account for.

On top of that, I’ve had issues with seamless performance with crossplatform SVG animations… but if the moons of Arrakis align just right you can make interactive SVGs work!

HTML & JavaScript on a Canvas Element

Two things:

  1. This violates the need to be simple and modifiable by everyone.
  2. It’s kind of a pain in the ass for rapid prototyping! 😛

Nuff said.

3rd Party Animation Library

Look, I’m not going to say it’s not doable, but… it’s going to be a lot like that time Napoleon marched across the alps… extravagant and full of propaganda and in the end you’re left asking “Why?” and declaring “Never again!”!

I won’t subject my audience to that level of abuse!

Still Frames

After considering all options available, Sam and I decided to go with still frame animation because it would be the easiest for non-coders to play with and it is the only option left standing after reviewing all the other options!

Simply put, everybody can draw a picture.

You can use these raster image editors if you don’t already have one:

I use GIMP for manual raster image work by choice (it indiscriminately works on Win, Mac & Linux, but the fact it’s free ain’t half bad either!) and Photoshop is a good choice also.

Although, I would add that having to run Photoshop on a virtual machine to be able to use it on Linux after having paid for it is BS!

GIMP is a lot like VISA (not a sponsor!) it’s everywhere you want to be, though unlike VISA there are no late payments!

Oh, and uh… in case it’s not abundantly clear, #its_never_a_sponsor!

“WHAT?! You mean… we have to draw every face permutation?”

No! Of course not! That would be wasteful & magically delicious… I mean… silly & redundant!

We just need to draw each isolated component but we’ll probably get into all that next week or the week after assuming I don’t take the opportunity to write about Project Orion for Columbus Day because that just totally makes sense to me. 😛

Front-End Code – MrGoodBot.php

Below is the code for this week, it creates a web page and uses CSS to add a little style!

There is a select dropdown element used for changing the skin, the “value” property is the name of the subfolder the skin is in, note it will be case sensitive on Linux.

After that there is an image tag with the element id of “face” and as you might guess this is the DOM object we use to draw Mr. Good Bot’s face.

Lastly, there is a little JavaScript that uses AJAX “POST” requests to change the face image.

Note the random numbers appended to the source link image name to prevent browsers from caching the image and not updating after it is loaded the first time:

Face.src = ‘skins/current_face.png?’ + Math.random();

Once the new face image is loaded, a timeout is used to wash, rinse & repeat ad infinitum with the decisions for assembling the face left to the backend code which we’ll cover in an upcoming post.

As is, when loaded you will just get a black screen but this code is boilerplate and fully functional and ready to display our bots face.

The Code

Copy -> Paste -> Run!

<!DOCTYPE html>
<html lang="en">
<title>Mr Good Bot</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
    background-color: #000;
    overflow: hidden;
}
.pullright{
    float:right;
    text-align:right;
} 
</style>
<body>

<select id='skin' class='pullright'>
    <option value='Default'>Default</option>
    <option value='Nucleus'>Nucleus</option>
    <option value='Pixel'>Pixel</option>
    <option value='Pumpkin'>Pumpkin</option>
</select>

<img src="" style="width:100%" id='face'>

<script>
var Face = document.getElementById('face');
function AnimateFace(){       
   var httpRequest = new XMLHttpRequest();
   var Skin = document.getElementById('skin');
   Skin = 'skin=' + Skin.options[Skin.selectedIndex].value;
   httpRequest.onreadystatechange = function(){
      if(httpRequest.readyState == 4 && httpRequest.status == 200){
         Face.src = 'skins/current_face.png?' + Math.random();
         setTimeout(AnimateFace, 120 * Math.floor(Math.random() * 11) + 1);
      }
   }
   
   httpRequest.open('POST', 'Face.php', true);
   httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
   httpRequest.send(Skin); 
}
AnimateFace();
</script>

</body>
</html>

Mr. Good Bot Goes to GitHub

You can follow along for free on GitHub as I release and update Mr. Good Bot’s code.

GitHub: MrGoodBot

 

Mr. Cool Bot Wallpaper

In keeping with last weeks Good Bot themed, time-honored tradition of including a wallpaper, here’s another, please enjoy!

Mr. Cool Bot Wallpaper

Mr Cool Bot 1920 x 1280 Wallpaper
Mr Cool Bot 1920 x 1280 Wallpaper

 

Next week we’ll look at how to create faces & skins for Mr. Good Bot but for now it looks like my ride is here so I’ll see you all next time and thanks for reading!

 


If it is by will alone that you love bots then set your mind in motion!

May thoughts acquire speed, bots acquire stains, the stains become you supporting my content through Patreon for $1 or more every month!

But, if all you can do is like, share, comment and subscribe… well that’s cool too!

Much Love,

~Joy

 

 

I Love Web Colors

Hello friends, I’m your “Web Colors“ girl!

Are your colors:

Tired

Rundown?

Listless?

Do they poop out at parties?

Are they unpopular?

The answer to all your problems is in this little bottle of Web Colors!

Web Colors contains all the Red, Green and Blue channels your colors need to spoon their way to bright vivaciousness!

So, why don’t you join the thousands of happy, peppy people, and enjoy a glass of Vitameatavegamin… er.. I mean Web Colors!

And who knows… with a little practice you will likely come to prefer the flavor over regular RGB notation because it’s shorter and as Lucy once said, It’s just like candy!

It’s so tasty, too! While being only 23% Alcohol by Volume, so no less capable! 😉


Continue reading “I Love Web Colors”

SVG Platformer

Can you go from art to program in one or two steps? Well, that’s what today’s post is about.

One of the cool things I remember about web development from years ago was Adobe Flash.

Before you boo me, hear me out!

I’m not saying Flash is a better technologically than HTML5, The Name of Your Favorite JavaScript Framework, CSS, Web Assembly etc… However one place Flash excelled was visual design & layout… an important part of the web!

The problem with many modern tools isn’t that they can’t convey design, it’s that they decouple the design and the development processes!

In practice this means writing code to describe the elements of your software like HTML and later writing more code to style the elements (like CSS, SASS or LESS), none of which is actually visual, though you definitely can get some great results!

Flash Builder (or whatever it was called) was half art studio and half IDE (Integrated Development Environment) where you could draw anything and it was an “object” and you could write code (ActionScript) to control it’s behavior. It wasn’t a mockup or illustration, it was the actual program!

As I recall, once the switch to ActionScript 3 was made the ability to store your code on the objects themselves was depreciated in favor of using references and listeners stored in the main keyframe timeline… I preferred keeping my code on the objects themselves but I digress.

Even with the change to where you stored your code you could still accomplish anything you wanted with the centralized keyframe code and some developers even found this easier to maintain than storing the code on the components.

You would setup your scripts on layered keyframe’s that extended to the last keyframe used in the project, or the last frame that needed that code and by using a sort of “goto keyframe name or id” method you could actually build complex applications quite easily, and more importantly… visually!

That’s why all the games used to be made with Flash, you could basically draw a picture and then turn it into an animation or even a full program in a couple of hours. This meant you were free to experiment & push boundaries.

Now, yes of course there are visual workflows you can use today.There are WYSIWYG editors and CMS App Platforms like WordPress, Drupal & Joomla not to mention the full featured layout capabilities of site builder tools like Wix.

Fundamentally though these tools facilitate laying out HTML elements and applying CSS and maybe some JavaScript via a drag and drop interface. Which is significantly faster than doing visual development via code in my opinion, though I am not arguing it is inherently “better”.

Unlike the aforementioned tools which specialize in “page based” HTML applications, Flash was an element or object that you embed into your page that used Vector Graphics to create lossless re-sizable images, animations and applications.

Inside the Flash movie/app you could draw anything and you were not constrained to HTML elements but you were also not required to code the visual elements.

This made for a wonderfully rapid prototyping experience that I was unable to reproduce until I tried working with Unity 3D which describes itself as “the ultimate game development platform” though I’d go so far as to describe it as “the ultimate app development platform”.

Think about it, at the time of writing this Unity supports 25 Platforms including Desktops (Win/Mac/Linux), the mobile OS’s, and all the major gaming consoles, not to mention the Smart TV’s, Watches etc…. Any platform you want your app on, including the web, well… Unity pretty much supports it right out of the box. Oh, and it’s free until you make $100K a year with it, not too shabby!

The catch? Well, its highly optimized but leans in the 3D gaming direction (though I’ve built 2D apps with Unity) so the applications it produces tend to have a larger size (as far as my tests go) than if you used PhoneGap/Cordova or went native. My guess is this is due to the embedded physics engine and graphics rendering code that gets packaged with the app but i’m only guessing, and there are a few options that let you exclude unnecessary things from the compiled app.

Then again, you may be able to make use of those features in your app so it need not be a negative either.

In any case, the problem as I see it with Unity is that the builder isn’t readily available on Linux, but it will build for Linux ❓ Maybe they should build Unity with Unity so that it can Unity being Unity… 😛

I am aware they kinda released a limited version for Linux… but I could never seem to make it work right and the truth is that it takes some decent (but not outrageous) resources to run the Unity builder application so most micro computers are out and sadly it won’t run on the ARMf architecture so using a Raspberry Pi to do Unity development is just not happening.

Is there another way?

Well, there is a modern Vector Graphic format available for the web called SVG that is basically XML code that can be written in a text editor or it can be drawn using a program like Inkscape (free and what I use) or Adobe Illustrator if you prefer a commercial paid tool.

Since SVG is code, if you place the code inside your HTML (sadly not link to or embed) you don’t just get a static vector image but instead you get elements that are accessible via the DOM (Document Object Model) that you can manipulate using CSS and JavaScript.

That last part should really interest you if you enjoy rapid application prototyping!

Which is the origin of this project, I wanted to know… could I rapid prototype an application by just drawing a picture and writing some code?

Understand that I am not talking about drawing a picture, slicing it then building an app from sliced components or using the sliced images as placeholders or writing code to draw the slices onto a canvas context.

I challenged myself to see if I could only write code that was part of the core functionality and not basic graphic asset creation and certainly not the code to display it, just manipulate it.

I set about creating a very simple “proof of concept” a while back that is basically a “Die Rolling App” that you can view a live example of here: SVG Roller though I never wrote about it. Roller is half image and half app but very basic.

Roller consists mainly of showing and hiding elements in the SVG based on a button click and a random number… good but not all that flashy!

Recently I have been wanting a better SVG application that would be more visual and expand on what I have already done but retain the simplicity of “Draw It then Code it”.

So, I opened up Inkscape and drew this image:


I grouped all the associated assets and gave them id’s like “cloud1”, “player”, “coin2” etc… then saved the image as demo.svg and closed Inkscape.

Why a game? Well, it’s more visual than my SVG Roller and I think it illustrates more of what is possible with an SVG app.

After that I opened demo.svg with a text editor and copied the SVG code into the body tag of my HTML file (remember you can’t link to it you have to include the code in the HTML).

I then wrote a little CSS that helps position the SVG on the page, applied a background color, disabled text highlighting and changed the cursor to the hand icon when the mouse is over a button, minimal CSS.

After that I wrote the JavaScript that turns the image into a playable application.

Game.js

Here is all the code that makes the SVG Platformer game demo work:

var keyEvents = {}; // keyboard state object

// Listen to keyboard outside of game loop to be less "blocky"
var onkeydown = onkeyup = function(key){
  key = key || event; // IE Fix 😦

  if(key.type == 'keydown'){
    keyEvents[key.keyCode] = true;
  }
  else{
    keyEvents[key.keyCode] = false; 
  }
  //console.log(keyEvents);
}


var game = document.getElementById('game'); // A reference to the SVG
if(game){
    game.addEventListener("load",function(){
    ///////////
    // Functions
        
    // Clear Instructions    
    // removes the instructions element
    function ClearInstructions() {
      instructions.remove();
    }

    // Get Position
    // This function gets the current (x,y) cordinates of GetPosition(object)     
    function GetPosition(object){
      var transformlist = object.transform.baseVal;
      var group = transformlist.getItem(0);
      var X = 0;
      var Y = 0;
      if (group.type == SVGTransform.SVG_TRANSFORM_TRANSLATE){
        X = group.matrix.e;
        Y = group.matrix.f;
      }
      return [X, Y];
    }
    
    // Collide
    // A basic box collision detector
    function Collide(element1, element2) {
      var collisionBox1 = element1.getBoundingClientRect();
      var collisionBox2 = element2.getBoundingClientRect();

      return !(collisionBox1.top > collisionBox2.bottom ||
        collisionBox1.right < collisionBox2.left ||
        collisionBox1.bottom < collisionBox2.top ||
        collisionBox1.left > collisionBox2.right);
    }

    // Inside
    // A basic inside box collision detector
    function Inside(element1, element2) {
      var collisionBox1 = element1.getBoundingClientRect();
      var collisionBox2 = element2.getBoundingClientRect();

      return (collisionBox1.top <= collisionBox2.bottom && 
        collisionBox1.bottom >= collisionBox2.top && 
        collisionBox1.left <= collisionBox2.right && 
        collisionBox1.right >= collisionBox2.left);
    }
      
    // Get Bank Total
    // Get the number of diamond or coins the player has
    function GetBankTotal(element){
      var currentValue = element.textContent;
      return parseInt(currentValue);
    }
    
    // Collect 
    // Increment the Coin or a Diamond "player bank"
    function Collect(element){
      element.textContent = GetBankTotal(element) + 1;
    }
      
    
            
    ///////////
    // Game play
    
    // Set the "constants"
    var step = 1;
    var jump = 20;
    var gravity = 1.5;

    // Setup references to the "named" SVG XML elements
    var gameOver = game.getElementById("gameover"); // A hidden "eater/detector" element below the play area to detect player death
    var instructions = game.getElementById('instructions');  // Instructions element
    var gameOverMenu = game.getElementById("gameovermenu");  // Game over screen element
    var player = game.getElementById("player");              // The player element
    var playerCoins = game.getElementById("playercoins");    // The "bank" element showing how many coins the player has collected
    var playerDiamonds = game.getElementById("playerdiamonds");// The "bank" element showing how many diamond the player has collected

    //  Setup references to the "named" SVG XML coin elements
    var coinPieces = ['coin1', 'coin2'];
    var coins = [];
    coinPieces.forEach(element => {
      coins.push(document.getElementById(element));
    });
        
    // Setup references to the "named" SVG XML diamond elements
    var diamondPieces = ['diamond1'];
    var diamond = [];
    diamondPieces.forEach(element => {
      diamond.push(document.getElementById(element));
    });

    // Setup references to the "named" SVG XML ground elements
    var terrainPieces = ['ground1', 'ground2', 'ground3', 'ground4'];
    var terrain = [];
    terrainPieces.forEach(element => {
      terrain.push(document.getElementById(element));
    });

    var winningBankTotal = diamondPieces.length + coinPieces.length;


    // Clear the instructions after 3 seconds
    setTimeout(ClearInstructions, 3000);


    // Redraw Game Loop
    var redrawRate = 30; // microseconds
    var gameLoop = setInterval(function(){
      fall = true; // always try to fall
      allowedToJump = false;// disallow jumping because player might be falling
      allowedToMove = true; // allow moving until the player is dead

      // Check for collisions with ground elements
      terrain.forEach(ground => {
        // If there is a collision with the ground
        if(Collide(player, ground)){
          fall = false; // Stop falling
          allowedToJump = true; // Allow jumping
        }
      });

      // if player fell below the ground
      if(Inside(player, gameOver)){
        fall = false; // stop falling
        allowedToJump = false; // dont allow jumping
        allowedToMove = false; // player is dead stop player movment
        ClearInstructions(); // just in case
        gameOverMenu.style.display = "inline"; // show game over menu
      }


      // if there was no collision between a ground element and
      // the player
      if(fall === true){
        position = GetPosition(player); // get updated player position
        allowedToJump = false; // dont allow jumping
        player.transform.baseVal.getItem(0).setTranslate(position[0], position[1] + gravity); // player falls
      }


      if(allowedToMove === true){
        position = GetPosition(player); // get updated player position
        // keyboard movment
        // left || a
        if (keyEvents[37] === true || keyEvents[65] === true) {
          if(position[0] > -10){
            player.transform.baseVal.getItem(0).setTranslate(position[0] - step, position[1]);
          }
        }
        // right || d
        if (keyEvents[39] === true || keyEvents[68] === true) {
          if(position[0] < 140){
            player.transform.baseVal.getItem(0).setTranslate(position[0] + step, position[1]);
          }
        }
        // up || w || space
        if ((keyEvents[38] === true || keyEvents[87] === true || keyEvents[32] === true) && allowedToJump === true) {
          player.transform.baseVal.getItem(0).setTranslate(position[0], position[1] - jump);    
        }
        // down || s
        if (keyEvents[40] === true || keyEvents[83] === true) {
          //console.log("Down");
        }
      }


      // Item Collection        
      // Collect coins
      coins.forEach(coin => {
        if(Inside(player, coin)){
          coin.remove();
          Collect(playerCoins);
        }
      });

      // Collect diamond
      diamond.forEach(diamond => {
        if(Inside(player, diamond)){
          diamond.remove();
          Collect(playerDiamonds);
        }
      }); 

      // Check for Win
      if((GetBankTotal(playerDiamonds) + GetBankTotal(playerCoins)) == winningBankTotal){
        clearInterval(gameLoop); // stop the game
        fall = false; // stop falling
        allowedToJump = false; // dont allow jumping
        allowedToMove = false; // player won stop player movment
        gameOverMenu.style.display = "inline"; // show game over menu
        // Change Game Over text to You Win
        game.getElementById("gameovermessage").textContent = '  You Win!';
      }

    }, redrawRate); // Game Loop - redraw every 30 microseconds
  }); // game load event listener
} // if game

 

As you can see from the code it supports WASD as well as the arrow keys and spacebar for movment. There is a win condition if you collect the two coins and the single diamond. You lose if you fall into one of the two spike pits.

Overall I am pleased with what I accomplished however the collision detection could be improved and there is quite a bit of room for improving how items are collected and enemies would be nice in addition to a larger/longer level, and maybe even a parallax scrolling  effect on some background elements as the player moves would also be nice, though again, I am happy with how it turned out.

You can Play a Live Demo: Here

You can Get the Code: Here

You can find a list of all my other posts on my Topics and Posts page.

I hope you enjoyed reading about and playing this SVG game prototype.

Your financial support allows me to dedicate time to developing projects like this and while I am publishing them without cost, that isn’t to say they are free. It takes me a lot of time and effort to build and publish projects like this for your enjoyment.

So I ask that if you like my content, please support me on Patreon for as little as $1 or more a month.

Feel free to suggest a project you would like to see built in the comments and if it sounds interesting it might just get built and featured here on my blog for you to enjoy.

 

 

Much Love,

~Joy

Button CSS Generator

Today we’re going to talk about a limited “generative system” that “writes” CSS code though I wouldn’t call this a ‘bot’.

What this generator does is “explore” the existing possibilities of a predefined problem space using known ranges and random selection. 😉

I wrote some of my thoughts regarding “generative systems” in relation to programmers and software developers in my article The Death of the Programmer and I also implemented a generative “writer bot” that I trained and used to write my article A Halloween Tale.

However in those cases I was mainly referring to semi-intelligent (in regard to the problem space) systems (“bots”) that are able to make choices on their own their own, and or are capable of learning, evolving or growing in some capacity based on input or state but that is not what we are doing today.

This is a simple generative tool (the Button CSS generator I provide below) is useful but it has no knowledge of what looks good (or bad) and no way to learn them either!

It can only provide you with options but it is far from replacing you.

You can view a Live Preview: Here 

Though in case you wanted it, here’s a screenshot:

There are only 3 files used to create the Button CSS generator: style.css, functions.js & index.html

Style.css

This is the CSS styles used by the index.html file. You will notice that there is a base button CSS template that all the buttons share when the page is first loaded.

The “hardcoded” styles are: text-align,  text-decorationdisplay, padding, font-size.

Once the page is loaded however I use JavaScript to generate and apply additional CSS attributes which are responsible for the variations in each button that you see.

The style.css file is an external style sheet and is linked to using <link rel=”stylesheet” type=”text/css” href=”style.css”> in the HTML file.

 

h1{
    width:100%;
    text-align: center;
}
    
button {
    /* hardcoded styles*/
    text-align: center;
    text-decoration: none;
    display: inline-block;
    padding: 15px 32px;
    font-size: 1.5em;
}

table{
    text-align: center;
    width:100%;
}

caption{
    font-size:2em;
}

#randomize{
    background-color: rgb(62, 176, 239); 
    color: rgb(138, 219, 215);
    border-color: rgb(28, 65, 39);
    border-width: 11px;
    border-style: dotted;
}

#show-css-wrapper{
    width: 100%;
    text-align: center;
    margin-left: auto;
    margin-right: auto;
}

#show-css-title{
    width: 100%;
    text-align: center;
    margin-left: auto;
    margin-right: auto;
    background-color: #999999;
}

#show-css{
    width: 40%;
    min-width: 420px;
    text-align: left;
    margin-left: auto;
    margin-right: auto;
    background-color: #eeeeee;
}

textarea{
    width: 100%;
    height: 200px
}

 

Functions.js

This file contains all the functions that the generator will use to make new button CSS styles.

There is some inline JavaScript in the HTML file that makes use of these functions and I will discuss that in the Index.html section below.

There is a lot of similarity between most of the functions and although much of their functionality can be wrapped up into one function I intentionally implemented the prototype generator this way.

I could say the reason is that I wanted to avoid early optimization but the real reason is that this way is just easier to read for someone who didn’t write the software and or is just learning to code.

Though in truth SetBackgroundColor(element) or SetBorderWidth(element) is not significantly more readable than a more optimized generic function like SetCSS(element, cssProperty,  optional [ value ])  and if I was going to spend more time developing this system I would probably end up going that route because the generic function would be far easier to maintain in the long run simply because it would be one function to maintain instead of many.

The functions.js file is an external script and is linked to the HTML file using the “src” (source) attribute on a script tag.

////////////////////////////////////
// Random Button CSS Generator Functions

// Will return 0 or 1
function CoinFlip(){
    return Math.floor(Math.random() * 2); //0/1
}
    

// Return a random string of RGB values e.g. "255, 255, 255"
function RandomRGBColor(){
    var r, g, b;
    
    r = Math.floor(Math.random() * 256);
    g = Math.floor(Math.random() * 256);
    b = Math.floor(Math.random() * 256);
    
    color = r.toString() + ', ' + g.toString() + ', ' + b.toString();

    return color;
}

// Set SetBackgroundColor()
function SetBackgroundColor(element, color = null){
    // No color given so set to random
    if(color === null){
        element.style.backgroundColor = 'rgb(' + RandomRGBColor() + ')';
    }else{ // Set to provided color
        element.style.backgroundColor = 'rgb(' + color + ')';
    }
}

// Set SetFontColor()
function SetFontColor(element, color = null){
    // No color given so set to random
    if(color === null){
        element.style.color = 'rgb(' + RandomRGBColor() + ')';
    }else{ // Set to provided color
        element.style.color = 'rgb(' + color + ')';
    }
}

// Set SetBorderColor()
function SetBorderColor(element, color = null){
    // No color given so set to random
    if(color === null){
        element.style.borderColor = 'rgb(' + RandomRGBColor() + ')';
    }else{ // Set to provided color
        element.style.borderColor = 'rgb(' + color + ')';
    }
}

// Set SetBorderWidth()
function SetBorderWidth(element, width = null){
    // No width given so set to random
    if(width === null){
        element.style.borderWidth = Math.floor(Math.random() * 14).toString() +'px';
    }else{ // Set to provided color
        element.style.borderWidth = width.toString() + 'px';
    }
}

// Set SetBorderStyle()
function SetBorderStyle(element, style = null){
    // No width given so set to random
    if(style === null){
        
        var styles = ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset', 'initial', 'inherit'];
        
        element.style.borderStyle = styles[Math.floor(Math.random()*styles.length)];
            
    }else{ // Set to provided color
        element.style.borderStyle = style;
    }
}

// Get the CSS for the button that was clicked and show it on the page
function ShowCSS(element){
    var style = window.getComputedStyle(element);
    var backgroundColor = style.getPropertyValue('background-color');
    var color = style.getPropertyValue('color');
    var borderColor = style.getPropertyValue('border-color');
    var borderWidth = style.getPropertyValue('border-width');
    var borderStyle = style.getPropertyValue('border-style');
    var padding = style.getPropertyValue('padding');
    var textDecoration = style.getPropertyValue('text-decoration');
    var display = style.getPropertyValue('display');
    var fontSize = style.getPropertyValue('font-size');
    var css = '';
    css += 'button{\n';
    css += '    background-color: ' + backgroundColor.toString() + ';\n';
    css += '    color: ' + color.toString() + ';\n';
    css += '    border-color: ' + borderColor.toString() + ';\n';
    css += '    border-width: ' + borderWidth.toString() + ';\n';
    css += '    border-style: ' + borderStyle.toString() + ';\n';
    css += '    padding: ' + padding.toString() + ';\n';
    css += '    text-decoration: ' + textDecoration.toString() + ';\n';
    css += '    display: ' + display.toString() + ';\n';
    css += '    font-size: ' + fontSize.toString() + ';\n';
    css += '}\n';

    document.getElementById('css-styles').innerHTML = css;
}

Index.html

Index.html is the core that brings all the pieces of this software together!

You will notice that I used divisional elements (div tags) and a textarea to create the section at the top of the page where the CSS code is shown when you click one of the buttons.

Beneath that is the randomize button hyperlinked to nothing, followed by a table. Why a table and not a responsive grid? Eh… it was faster for the prototype mainly.

Inside each cell of the the table is a button that has an onclick attrabute that passes the element’s ID reference ‘this’ to the function ShowCSS().

Beyond this the only thing of consequence in the HTML file is the inline JavaScript that uses the code from the functions.js script to make everything work.

When the page loads I use an array of strings of element id’s (the buttons) to locate & establish references to the DOM objects for each button and store those references in the buttons array.

Then, for each of the element references in the buttons array I set a background color as well as a font color randomly. After that I “flip a coin” to decide if a boarder should be applied to the button. If yes, I apply a random boarder color, width and style.

Once the code is done running all the buttons will be randomly styled and are ready for you to click them to get the CSS if you like them or click Randomize to get a new set of random buttons.

<html>
<head>
  <title>Random Button</title>
  <link rel="stylesheet" type="text/css" href="style.css"> 
</head>
<body>
  <!-- Title -->
  <h1>Random Button CSS Generator</h1>
     
    <!-- Show CSS -->
    <div id="#show-css-wrapper">
        <div id="show-css">
            <h2 id="show-css-title">Button CSS</h2>
            <p>Select a button to view it's CSS styles</p>
            <textarea id="css-styles">CSS will show here</textarea>        
        </div>
    </div>

    <!-- Table -->
    <table> 
      <tr>
          <td></td>
          <td>
              <h3>
                  <a href="">
                      <button id="randomize">
                          Randomize
                      </button>
                  </a>
              </h3>
          </td>
          <td></td>
      </tr>
         <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
      </tr>
      <tr>
        <td><button id="button-1" onclick="ShowCSS(this)">Button 1</button></td>
        <td><button id="button-2" onclick="ShowCSS(this)">Button 2</button></td>
        <td><button id="button-3" onclick="ShowCSS(this)">Button 3</button></td>
      </tr>
      <tr>
        <td><button id="button-4" onclick="ShowCSS(this)">Button 4</button></td>...
        <td><button id="button-5" onclick="ShowCSS(this)">Button 5</button></td>
        <td><button id="button-6" onclick="ShowCSS(this)">Button 6</button></td>
      </tr>
        <tr>
        <td><button id="button-7" onclick="ShowCSS(this)">Button 7</button></td>
        <td><button id="button-8" onclick="ShowCSS(this)">Button 8</button></td>
        <td><button id="button-9" onclick="ShowCSS(this)">Button 9</button></td>
      </tr>
    </table>

 
    <!-- Include the Functions -->
    <script src="functions.js"></script>    
    <script>
    // Button Element ID's
    var elementsIDs = ['button-1', 'button-2', 'button-3', 'button-4', 'button-5', 'button-6', 'button-7', 'button-8', 'button-9'];

    var buttons = []; // Array to Store Button References

    // Setup Element References to the Buttons
    elementsIDs.forEach(element => {
      buttons.push(document.getElementById(element));
    });

    // Apply Random CSS to each Button
    buttons.forEach(element => {
      SetBackgroundColor(element); // Set Initial Background Colors
      SetFontColor(element);       // Set Initial Font Colors

      if(CoinFlip() == 1){ // Has border?
        SetBorderColor(element);
        SetBorderWidth(element);
        SetBorderStyle(element);
      }
       
    });

    </script>
</body>
</html>

 

Where to go from here

As a proof of concept I think I accomplished my goal of creating a functional Button CSS Generator however a more complete prototype would want to include features like allowing you to edit the CSS of the selected button and have the changes reflect on the button in real time or via an “update” button.

Also, perhaps the ability to “favorite” or save a button’s CSS style so that you can reload it again later or some kind of “history” feature would be nice so that you can keep the button styles you like.

Additionally, the CSS attributes the generator uses are hard coded and the property or attribute “min/max” ranges are set as well… A nice feature would be be to have the option to edit/add or remove the CSS fields included in the generator and modify the ranges as well.

It would also be nice for the prototype to allow for the generation of vertical and horizontal menus using the button CSS and include the ability to edit the links or “onclick” actions and the text of the buttons.

The “ultimate” implementation of a generator like this would allow you to generate styles for all or some subset of the HTML elements not just buttons.

I will leave all these features for you to add to your own implementations at this time however if you like this project I may just add some or all of these features in the future.

You can view a Live Preview: Here

You can get the code on GitHub: Here

You can find a list of all my other posts on my Topics and Posts page.

I hope you enjoyed reading this article.

Your financial support allows me to dedicate time to developing projects like this and while I am publishing them without cost, that isn’t to say they are free. I am doing this all by myself and it takes me a lot of time and effort to build and publish these projects for your enjoyment.

So I ask that if you like my content, please support me on Patreon for as little as $1 or more a month.

Feel free to suggest a project you would like to see built in the comments and if it sounds interesting it might just get built and featured here on my blog for you to enjoy.

 

 

Much Love,

~Joy

 

Ancestor Simulations Generating New Solar Systems Monday Mini Makeup

Happy Monday!

MY LOGIC IT FEELS GOOD TO BE BACK POSTING! Did you miss me? I know it has been only one week but I missed me! 😛

The truth is that as much as I keep making these projects and posts for you guys, I REALLY need this! The act of sitting down and thinking up not just a programming project every week, but also something that is intelligent (and hopefully entertaining) has been extremely cathartic for me!

You see, as much as your job may be difficult (it probably is) and boring at times (likely) and as much as your coworkers, clients, boss or employees can be a pain (It’s Monday so I know you are thinking it), all of those people are rational and you have every right to your frustrations!

I share no such luxury my friend because my boss is an irrational 7 month old baby who only loosely knows the words “baba” and “momma” !

Don’t misunderstand me, I certainly love my little Xavier, it’s just that unlike your adult employees, bosses, coworkers, clients, G/F, B/F, spouse, lover, spouse’s lover… what have you 😛 whose thoughts and motivations you can basically understand with a reasonable amount of effort and discussion, no matter how many times I carefully explain the dangers of wantonly crawling off the edge of the bed head first onto a hardwood floor he still takes every opportunity to try!

Further still, no matter how many times I explain how it hurts momma when he imagines himself as Tarzan and attempts to use my hair as vines to swing on and yet alas… he is just not amenable to the idea!

Regardless of the countless times I elaborate on why wiggling around when I am changing his “poopy” diapers creates “yucky messes” for momma to clean up, it is none the less… ineffectual!

The jarring truth is that you simply cannot reason with a 7 month old baby! Odds are at the very least, the people you deal with every day are leaps and bounds (many orders of magnitude) more acquiescent to compromise than Xavier is!

As such, I have confidence that you will get through this week with aplomb! 😉

Now, let’s talk about our Ancestor Simulation, shall we?

When you last saw this project Generating New Solar Systems I was getting ready for a “Friday Fun Fix” and I was contemplating the following three modifications to the Solar Systems Generator:

  • Adding loss of mass  to thermal energy release and heat transfer when there are impacts of orbital bodies.
  • Improved agglomeration of smaller particulates into larger bodies.
  • Adding chemical properties and transfer those chemicals during impacts.

First let me say that I feel like accounting for mass lost as thermal radiation released during orbital body impacts is an absolutely wonderful idea! However, at this point it is seemingly a bit more complex than we currently have the resources to model. If you think about it, we would have to keep track of subdivisions of masses and implement a much more complex particle simulation (not to mention model all the subatomic particles) and then extend that system (additional computation) to every frame (epoch) of the simulation… while this is a wildly fun idea, I don’t really feel like we would get all that much out of adding this at this juncture. So, I have decided that we are going to shelve this concept for the time being and perhaps at a later date, once we have upgraded our computational capacity we may revisit this.

In regard to improving agglomeration and instantiating our solar system from smaller particulates into larger bodies. We had implement collision detection and our planets would eat each other, quite vigorously in fact! However, more often than not we would end up with few stable orbits (one or two) but usually no sustained orbits. After a bunch of minor tweaks late this past week and weekend throughout the generator I have managed to get it to a state of routinely generating complex multi-body orbital patterns and I tweeted a teaser GIF on Friday:

Many of the code “tweaks” involved modifying the initialization of the orbital velocities and distance from the center star. What the planets currently do is basically “find their orbits” starting with an orbit larger than their velocity can sustain so their orbits decay from their initial position to an inner orbit closer to the sun. Once their velocity is sufficient to maintain the bodies distance from the sun it continues to orbit until it collides with something or the simulation ends.

I am now quite pleased with the behavior of the simulation in regard to agglomeration at this point however I really wish we had the ability to extend this further and implement something akin to an accretion disk from which the orbital bodies form from clouds of material rather than instantiating small but fully formed planetoid’s which then proceed to ‘consume’ one another in order to grow. This too would require an improved particle system and at this time I don’t have enough ‘big iron‘ to make this a reality. Again though, I am really pleased with what I have accomplished already!

Further, I am toying with the idea of imposing a second “grid” overlay on the solar system that would contain a probability distribution of “virtual particles‘ (perhaps using a modified version of the plasma fractal which we already implemented over in my post on Generating Planet Terrain) that could be used to organically “grow” planets without the need to simulate each and every atom and collision directly.

In this case we would say that as an orbital body passes through each position in the probability distribution, based on the density of “virtual particles” the centaurs would grow by some amount based on that position’s material abundance and at the same time reduce the available particulate in the cloud (probability distribution) thereby actually accreting using only probability and not simulating the individual interactions of the collisions.

If I have the opportunity I will toy with this concept a little and see if it is worth implementing in full.

Which brings us to the final enhancement under consideration, implementing a chemical or elemental system. Let me first say that this is HAPPENING for sure! I have the initial element system partially implemented already and if all goes well I expect to unveil this feature in this upcoming “Friday Fun Fix”. Additionally, while we need not limit ourselves to real elements (nothing says we can’t just make up a new periodic table for our simulated universe) we will however be using the same chemical elements as are available in our universe. 🙂

In any case here is a newly rendered solar system containing 19 stable orbital bodies.

Click or tap the animation to view it full size.

 

You can find the updated code for this project over on my GitHub profile.

Please Like, Comment below & Share this post with your friends and followers on social media.

Please support me over on Patreon for as little as $1 a month.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

As always, have a great week and I will see you all in my next post!

Much Love,

~Joy

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: