UISceneSession is only available in iOS 13.0 or newer

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Okay, so you’ve stumbled upon this terribly annoying error message: UISceneSession is only available in iOS 13.0 or newer, now what? The best answer is to simply update the software on the iPhone that you are trying to run your app.

The worse answer is to actually go in to the code by hand and add @available attributes to the parts of the boilerplate code generated by Xcode that aren’t compatible with the older version of iOS running on your test device. But in my opinion this is trying to swim against the current. Just go ahead and update the software on your phone and all will be well.

Although if I remember correctly, this is always going to be sort of a damned-if-you-update, damned-if-you-don’t-update sort of situation. You may end up finding yourself running into the opposite situation: You update the version of iOS on your iPhone, then the older version of Xcode becomes out of sync with your device. Unfortunately this is just the way of native mobile development— a never ending series of software updates.

 

How to Teach Turtle Graphics with Python

Quick little starter template for use teaching introductory python programming to students using the turtle graphics library =>

import turtle
screen = turtle.Screen()
screen.screensize()
screen.setup(width=1.0, height=1.0)
screen.addshape("sprite.gif")
sprite = turtle.Turtle()
sprite.shape("sprite.gif")
sprite.penup()
sprite.goto(0, 0)
sprite.goto(200, 200)
sprite.goto(-200, 200)
sprite.goto(-200, -200)
sprite.goto(200, -200)
sprite.goto(200, 200)
turtle.mainloop()
 

woohoo.cs

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Funny C# Winforms project/tutorial I built with one of my students. Inspired by woohooooo.com. Executable version coming soon…

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WoohooWinform
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Find File Path to Main Directory (Contains Main Program and Additional Files)
string pathToDirectory = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
// Create SoundPlayer Object Which Will Play Our WAV File
System.Media.SoundPlayer player = new System.Media.SoundPlayer();
// Tell The SoundPlayer Object Where Our WAV File is Located
player.SoundLocation = pathToDirectory + @"\woohoo.wav";
// Say Woohoo!
player.Play();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
view raw woohoo.cs hosted with ❤ by GitHub
 

Cordova Screen Orientation (Lock) Plugin Not Working

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

If you find yourself struggling to get the Apache Cordova screen orientation lock plugin to work, the problem is most likely that you are calling the .lock() method before the ‘deviceready’ event has fired. To fix this problem, simply create a call back function containing your .lock() method call, then pass this callback function as an argument to the deviceready event listener like so =>

First, make sure to install the screen orientation plugin for apache cordova

$ cordova plugin add cordova-plugin-screen-orientation

Then, rewrite your code to look something like this…

// Lock Device Orientation
function lockDeviceOrientationCallback() {
// set to either landscape
screen.orientation.lock('portrait');
console.log("locking device orientation...");
}
document.addEventListener("deviceready", lockDeviceOrientationCallback, false);
 

Pong in Python vs. Pong in JavaScript: Battle of Introductory Game Dev Tutorials

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Battle of the introductory game dev tutorials by myself and my student “Squitato” =>

# Copyright (c) 2018 Peter Kwak (Edited by Chris Pedersen)
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
import turtle
# Create Game Window
screen = turtle.Screen()
# screen.setup(500, 400)
screen.screensize(500, 500, "black")
screen.bgcolor("black")
# screen.addshape("Paddle.jpg")
# Create Ping Pong Ball
ball = turtle.Turtle()
ball.penup()
ball.speed(0)
ball.shape("circle")
ball.color("white")
# Create Left Ping Pong Paddle
paddle1 = turtle.Turtle()
paddle1.penup()
paddle1.speed(0)
paddle1.setx(-200)
paddle1.shape("square")
paddle1.shapesize(4.5, 1, 0)
paddle1.fillcolor("white")
# Create Right Ping Pong Paddle
paddle2 = turtle.Turtle()
paddle2.penup()
paddle2.speed(0)
paddle2.setx(200)
paddle2.shape("square")
paddle2.shapesize(4.5, 1, 0)
paddle2.fillcolor("white")
# Create Scoreboard
scoreWriter = turtle.Turtle()
scoreWriter.penup()
scoreWriter.speed(0)
scoreWriter.hideturtle()
scoreWriter.color("white")
# Set Ball Trajectory
rise = 3
run = 3
# Set Score
score1 = 0
score2 = 0
# Create Function Which Will Move Player 1's Paddle Up
def up1():
paddle1.sety(paddle1.ycor() + 50)
# Create Function Which Will Move Player 1's Paddle Down
def down1():
paddle1.sety(paddle1.ycor() - 50)
# Create Function Which Will Move Player 2's Paddle Up
def up2():
paddle2.sety(paddle2.ycor() + 50)
# Create Function Which Will Move Player 2's Paddle Down
def down2():
paddle2.sety(paddle2.ycor() - 50)
# Create Function To Update Scoreboard
def updateScoreboard():
global scoreWriter
global score1
global score2
global ball
scoreWriter.clear()
myFont = ("Arial", 40, "bold")
scoreWriter.goto(-100, 150)
scoreWriter.write(score1, font=myFont)
scoreWriter.goto(100, 150)
scoreWriter.write(score2, font=myFont)
ball.goto(0, 0)
# Set Event Listeners
# These event listeners will listen for button presses (up, down, etc.)
screen.onkey(up1, "w")
screen.onkey(down1, "s")
screen.onkey(up2, "Up")
screen.onkey(down2, "Down")
screen.listen()
# Create Main Game Loop (Simulates Time, Keeps Game Running)
while True:
# Move Ball
ball.goto(ball.xcor() + run, ball.ycor() + rise)
# Detect Top or Bottom Boundary Strike
# (Reverses the Ball's Direction of Travel)
if ball.ycor() > 200 or ball.ycor() < -200:
rise = -rise
# Detect Paddle Strike (Player 1)
# (Also Reverses the Ball's Direction of Travel)
if abs(paddle1.xcor() - ball.xcor()) < 15:
if abs(paddle1.ycor() - ball.ycor()) < 50:
run = -run
# Detect Paddle Strike (Player 2)
# (Also Reverses the Ball's Direction of Travel)
if abs(paddle2.xcor() - ball.xcor()) < 15:
if abs(paddle2.ycor() - ball.ycor()) < 50:
run = -run
# Detect When A Player Scores a Point
if ball.xcor() > 250:
# Increment player1's score by 1 point when his ball
# travels past the paddle of his opponent, player 2.
score1 = score1 + 1
updateScoreboard()
ball.goto(0, 0)
elif ball.xcor() < -250:
# Increment player2's score by 1 point when his ball
# travels past the paddle of his opponent, player 1.
score2 = score2 + 1
updateScoreboard()
ball.goto(0, 0)
# Christine, My Super Sweet AI Goes HERE...
if ball.ycor() > paddle2.ycor() + 25:
paddle2.sety(paddle2.ycor() + 15)
elif ball.ycor() < paddle2.ycor() - 25:
paddle2.sety(paddle2.ycor() - 15)
view raw pong.py hosted with ❤ by GitHub

NOTE: For the PongJS demo, you will need to manually install p5.play.js as it is not available via CDN =>

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<!-- NOTE: Must Download and Install p5.play.js Manually, it is not available via CDN -->
<script src="p5.play.js"></script>
</head>
<body>
<script src="pong.js"></script>
</body>
</html>
view raw pong.html hosted with ❤ by GitHub
//pong clone
//mouse to control both paddles
var paddleA, paddleB, ball, wallTop, wallBottom;
var MAX_SPEED = 10;
function setup() {
createCanvas(800, 400);
//frameRate(6);
paddleA = createSprite(30, height/2, 10, 100);
paddleA.immovable = true;
paddleB = createSprite(width-28, height/2, 10, 100);
paddleB.immovable = true;
wallTop = createSprite(width/2, -30/2, width, 30);
wallTop.immovable = true;
wallBottom = createSprite(width/2, height+30/2, width, 30);
wallBottom.immovable = true;
ball = createSprite(width/2, height/2, 10, 10);
ball.maxSpeed = MAX_SPEED;
paddleA.shapeColor = paddleB.shapeColor =ball.shapeColor = color(255, 255, 255);
ball.setSpeed(MAX_SPEED, -180);
}
function draw() {
background(0);
paddleA.position.y = constrain(mouseY, paddleA.height/2, height-paddleA.height/2);
paddleB.position.y = constrain(mouseY, paddleA.height/2, height-paddleA.height/2);
ball.bounce(wallTop);
ball.bounce(wallBottom);
var swing;
if(ball.bounce(paddleA)) {
swing = (ball.position.y-paddleA.position.y)/3;
ball.setSpeed(MAX_SPEED, ball.getDirection()+swing);
}
if(ball.bounce(paddleB)) {
swing = (ball.position.y-paddleB.position.y)/3;
ball.setSpeed(MAX_SPEED, ball.getDirection()-swing);
}
if(ball.position.x<0) {
ball.position.x = width/2;
ball.position.y = height/2;
ball.setSpeed(MAX_SPEED, 0);
}
if(ball.position.x>width) {
ball.position.x = width/2;
ball.position.y = height/2;
ball.setSpeed(MAX_SPEED, 180);
}
drawSprites();
}
view raw pong.js hosted with ❤ by GitHub
 

ModuleNotFoundError: No module named ‘Tkinter’

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Fret not dear pythoneer, all you need to do to fix this is change Tkinter to tkinter as the name of the module has changed in Python 3. Whoops! Also, make sure to change

print "stuff"
to
print("stuff")
and all will be well!

from tkinter import *
class Application(Frame):
def say_hi(self):
print("hi there, everyone!")
def createWidgets(self):
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
self.QUIT.pack({"side": "left"})
self.hi_there = Button(self)
self.hi_there["text"] = "Hello",
self.hi_there["command"] = self.say_hi
self.hi_there.pack({"side": "left"})
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
 

Deal or no Deal? by Alex W.

My Student Alex W just finished up his first app, Deal or No Deal. If you’d like to check it out, you can download the .apk to your Android phone by clicking the SourceForge download button below. Great work Alex!

Download DealOrNoDeal

NOTE: Please make sure to enable installation of apps from unknown sources on your Android device prior to downloading.

Settings > Security > Allow installation of apps from unknown sources

 

Roblox Scripting Lesson 0

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Quick little blog post here on how to get started with scripting in Roblox Studio. These two example scripts should be added under the ServerScriptService and the variable names should match the baseplate and part added to your blank starter project =>

local basePlate = game.Workspace.Baseplate
while true do
basePlate.BrickColor = BrickColor.new(1.0, 0.08, 0.58) --hot pink
wait(0.25)
basePlate.BrickColor = BrickColor.new(0.0, 1.0, 0.0) --lime green
wait(0.25)
basePlate.BrickColor = BrickColor.new(0.0, 1.0, 1.0) --aqua
wait(0.25)
basePlate.BrickColor = BrickColor.new(0.0, 1.0, 1.0) --purple
wait(0.25)
basePlate.BrickColor = BrickColor.new(1.0, 1.0, 0.0) --yellow
end
local practicePart = game.Workspace.PracticePart
while true do
practicePart.BrickColor = BrickColor.new(1.0, 0.08, 0.58) --hot pink
wait(0.25)
practicePart.BrickColor = BrickColor.new(0.0, 1.0, 0.0) --lime green
wait(0.25)
practicePart.BrickColor = BrickColor.new(0.0, 1.0, 1.0) --aqua
wait(0.25)
practicePart.BrickColor = BrickColor.new(0.0, 1.0, 1.0) --purple
wait(0.25)
practicePart.BrickColor = BrickColor.new(1.0, 1.0, 0.0) --yellow
end
 

Hello, World Tutorial with Turbolinks by topherPedersen & jaxatax

Really simple two page tutorial on adding Turbolinks magic to your traditional webapp in order to achieve a SPA (singe page application) feel without having to learn a complicated framework like React, Angular or Vue. Simply import Turbolinks, then call Turbolinks.visit() to load your pages in the background with Turbolinks & AJAX =>

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/turbolinks/5.2.0/turbolinks.js"></script>
<style>
body {
background-color: blue;
}
a {
color: white;
}
</style>
</head>
<body>
<button onclick="Turbolinks.visit('mylink.html');">click me</button>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
view raw mylink.html hosted with ❤ by GitHub
 

Adobe PhoneGap Hello, World APK

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

I’ve been experimenting at work with Apache-Cordova/Adobe-PhoneGap and am trying to find an easy way to distribute APKS generated using Adobe’s build service. Setting up development machines is probably too much work for the kids I teach, so just wanted to see if I can post an APK easily on my WordPress blog. So without futher ado… My Adobe PhoneGap Build Service Hello World APK =>

Download AdobePhoneGapHelloWorld