Z80 - Flappy B

Part 1 - Intro

 

zxsp - speccy emulator
pasmo - z80 compiler
bin2tap - convert binary file to tap file

Web links
http://www.speccyvirgins.com

https://chuntey.wordpress.com

http://chuntey.arjunnair.in

https://drive.google.com/file/d/0Bw7HZpJSTfpcWS0yNGVyREFsbnc/view

http://www.zxasm.net/index.php/2016/07/16/compo-6-256-byte-game-compo-the-results/

 

Part 2

The Code

The Video - Got myself confused, not hard to do with Z80 :)

Note to self - use a bigger font on editor next time!

Part 3

in progress

Episode 3 - I like Math

subscribe on iTunes 

So the new game I want the baddies to take several patterns across the screen, one of them is a SIN wave. Ended up using Excel to remind me of Radians and work out a formula to input amplitude which I can use for y axis size.

Thumberjack math and rotation?

func isFingerTouchingLine()->Bool{
....
    let minX = (xPos - (n.size.width / 2) ) - self.touchTolerance
    let maxX = (xPos + (n.size.width / 2)) + self.touchTolerance
    let minY = yPos - self.touchTolerance
    let maxY = yPos + n.size.height + self.touchTolerance
               
    if n.zRotation == 0 {
        if self.tloc.x >= minX && self.tloc.x <= maxX && self.tloc.y >= minY && self.tloc.y <= maxY {
            retval = true
        }
    } else {
        let testpoint = self.rotate_point(realpos, angle: -n.zRotation, p: self.tloc)
        if testpoint.x >= minX && testpoint.x <= maxX && testpoint.y >= minY && testpoint.y <= maxY {
           retval = true
       }
    }
....

return retval
}

func rotate_point(_ c  :CGPoint, angle :CGFloat,  p: CGPoint)->CGPoint{
        let newx = cos(angle) * (p.x - c.x) - sin(angle) * (p.y - c.y) + c.x
        let newy = sin(angle) * (p.x - c.x) + cos(angle) * (p.y - c.y) + c.y
        let new = CGPoint (x: newx, y: newy)
        return new
}
ThumberJack Rotated Objects

ThumberJack Rotated Objects

Where did I lean to code on Apple

https://www.raywenderlich.com

Don't throw the baby out with the bathwater.

Shark Attack

Shark Attack

 

Ironman Training 30 Weeks to go.

 

https://twitter.com/j0hnniemac

Music Licensed from : mobygratis.com - song: Rotator

Episode 2 - Submitting for Review is no fun

subscribe on iTunes 

Forget what need to be done for submitting for review

Splash Screen Issues

iconmaker - https://github.com/J0hnniemac/iconmaker

launchmaker - https://github.com/J0hnniemac/launchmaker

Manic Miner Run

swimmer class - early dev

 

//
//  ada.swift
//  SharkAttackDec2016
//
//  Created by John McManus on 07/12/2016.
//  Copyright © 2016 John McManus. All rights reserved.
//

import SpriteKit
class ada :SKSpriteNode{
    let gravity :CGFloat = 50.0
    var isGravityOn = true
    var rememberStartPosition : CGPoint!
    var isSwimming = false
    let adaTextures = [SKTexture(imageNamed: "Ada1"),SKTexture(imageNamed: "Ada2"),SKTexture(imageNamed: "Ada3"),SKTexture(imageNamed: "Ada4")]
    var adaAni :SKAction!
    convenience init(startNode :SKNode)
    {
        self.init(texture: SKTexture(imageNamed: "Ada1"))
        self.rememberStartPosition = startNode.position
        self.position = self.rememberStartPosition
        self.name = "playerAda"
        setupAni()
    }
    private func setupAni(){
        adaAni = SKAction.repeatForever(SKAction.animate(with: adaTextures, timePerFrame: 0.1))
    }
    func startSwim(){
    // start swim animation
        self.run(adaAni)
        isSwimming = true
    }
    func stopSwim(){
    //stop swim animation
        self.removeAllActions()
        isSwimming = false
    }
    func applyGravity(dt :TimeInterval){
        if !isSwimming {return}
        if !isGravityOn {return}
        let distance = gravity * CGFloat(dt)
        self.position.y = self.position.y - distance
    }
    func swimForceUp(){
        if !isSwimming {return}
            if !(self.action(forKey: "swimforce") != nil){
                let a1 = SKAction.moveBy(x: 0, y: 15, duration: 0.1)
                let a2 = SKAction.run {
                    self.isGravityOn = true
                }
                let seq = SKAction.sequence([a1,a2])
                self.run(seq, withKey: "swimforce")
            }
    }
    func update(dt :TimeInterval){
        applyGravity(dt: dt)
    }
}

Scenery Class - subclassing SKNode

//
//  scenery.swift
//  SharkAttackDec2016
//
//  Created by John McManus on 06/12/2016.
//  Copyright © 2016 John McManus. All rights reserved.
//

import SpriteKit
import GameplayKit
class scenery: SKNode {
    var bgSpeed: CGFloat!
    var bgTextures :[SKTexture]!
    //var bgPosition: bgPossiblePosition!
    var repititions : Int!
    var nodeList :[SKSpriteNode]!
    var totalLength :CGFloat = 0
    var overlap : CGFloat = 0
    var endX :CGFloat = 0
    
    convenience init( bgTextures :[SKTexture], bgSpeed :CGFloat, repititions:Int, overlap :CGFloat)
    {
        self.init()
        self.bgTextures = bgTextures
        //self.bgPosition = bgPosition
        self.bgSpeed = bgSpeed
        self.repititions = repititions
        self.overlap = overlap
        setupScenery()
    }
    private func setupScenery(){
        let maxBGs = bgTextures.count - 1
        var nextPosition = CGPoint.zero
        nodeList = [SKSpriteNode]()
        for i in 1...repititions {
            print(i)
            let nextText = GKRandomSource.sharedRandom().nextInt(upperBound: maxBGs)
            let nextPiece = SKSpriteNode(texture: bgTextures[nextText])
            nextPiece.position = nextPosition
            self.addChild(nextPiece)
            nextPosition.x = nextPosition.x + nextPiece.size.width - overlap
            nodeList.append(nextPiece)
            totalLength = totalLength + nextPiece.size.width - overlap
        }
        endX = (-totalLength / 2)
    }
    func scrollLeft(dt :TimeInterval){
        let delta = bgSpeed * CGFloat(dt)
        for p in nodeList{
            p.position.x = p.position.x - delta
            if p.position.x < endX {
            //move to end pos
                p.position.x = p.position.x + totalLength
            }
        }
    }

    func update(dt:TimeInterval){
        scrollLeft(dt: dt)
    }

}

Episode 1 - I can't draw

subscribe on iTunes 

Imagemagick colouring sprites

convert genconv1.png  -fill yellow -opaque white gengonv1-yellow.png

 

Colouring sprites in Swift

let colorize1 = SKAction.colorize(with: .blue, colorBlendFactor: 1, duration: 0.2)
let colorize2 = SKAction.colorize(with: .red, colorBlendFactor: 1, duration: 0.2)
let colorize3 = SKAction.colorize(with: .magenta, colorBlendFactor: 1, duration: 0.2)
let colorize4 = SKAction.colorize(with: .green, colorBlendFactor: 1, duration: 0.2)
let colorize5 = SKAction.colorize(with: .cyan, colorBlendFactor: 1, duration: 0.2)
let colorize6 = SKAction.colorize(with: .yellow, colorBlendFactor: 1, duration: 0.2)
let colorize7 = SKAction.colorize(with: .white, colorBlendFactor: 1, duration: 0.2)
let colSeq = SKAction.sequence([colorize1,colorize2,colorize3,colorize4,colorize5,colorize6,colorize7,colorize6,colorize5,colorize4,colorize3,colorize2])

colorCycleCollectables = SKAction.repeatForever(colSeq)

Tea is not Venti

Example of my early artwork (3 year ago)

A Padlock I drew yesterday

Creating Tutorial Scenes

Xcode Editor - Bah humbug

Code - Yeh. Use physic collisions to trigger actions.

 

 

 

Music Licensed from : mobygratis.com - song: Rotator

Episode 0 - I am not a programmer

Manic Miner Run

Screen 1, manic robot and conveyor belts.

 

TileMap issues

  • Xcode scene editor resetting to 32x32
  • no physics properties on tiles
  • change a user data value on a tile changes for all tiles.

Mapping Collectable

func addPhysicsKeys(){
        print(#function)
        let tileSize = roomMap.tileSize
        let halfWidth = CGFloat(roomMap.numberOfColumns) / 2.0 * tileSize.width
        let halfHeight = CGFloat(roomMap.numberOfRows) / 2.0 * tileSize.height
        let physicsCollectableOverlay = SKNode()
        for column in 0..<roomMap.numberOfColumns {
            for row in 0..<roomMap.numberOfRows {
                let objectTile = roomMap.tileDefinition(atColumn: column  , row: row)
                if let _ = objectTile?.userData?.value(forKey: "isCollectable") {
                    let x = ( CGFloat(column) * tileSize.width - halfWidth ) + (tileSize.width / 2 )
                    let y = ( CGFloat(row) * tileSize.height - halfHeight ) + (tileSize.height / 2 )
                    let texture = objectTile?.textures[0]
                    let shadowNode = SKSpriteNode(texture: texture, size: (texture?.size())!)
                    shadowNode.position = CGPoint(x: x, y: y)
                    let psize = CGSize(width: shadowNode.size.width * 0.90, height: shadowNode.size.height * 0.90)
                    shadowNode.physicsBody = SKPhysicsBody(texture: texture!, size: psize)
                    shadowNode.physicsBody?.isDynamic = true
                    shadowNode.physicsBody?.affectedByGravity = false
                    shadowNode.physicsBody?.categoryBitMask = physicsObject.Collectable
                    shadowNode.physicsBody?.collisionBitMask = physicsObject.None
                    shadowNode.physicsBody?.contactTestBitMask = physicsObject.WillyBody 
                    shadowNode.name = "Collectable"
                    physicsCollectableOverlay.addChild(shadowNode)
                    shadowNode.run(colorCycleCollectables)
                    roomMap.setTileGroup(nil, forColumn: column, row: row)
                    print("added collectable")
                }
            }
        }
        self.addChild(physicsCollectableOverlay)
    }