Skip to content

Instantly share code, notes, and snippets.

@ShihabM
Created November 3, 2021 09:53
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ShihabM/b75321e7f497f17ff3d9d65afd5557d6 to your computer and use it in GitHub Desktop.
Save ShihabM/b75321e7f497f17ff3d9d65afd5557d6 to your computer and use it in GitHub Desktop.
Dock Shooter - a game in your dock icon
//
// AppDelegate.swift
// Dock Shooter
//
// Created by Shihab Mehboob on 01/11/2021.
//
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
let bgView = NSView()
let shipView = NSImageView()
var timer: Timer?
var yLoc: CGFloat = 0
var score: Int = 0
var hideScore: Bool = false
let bullet = NSView()
let enemy = NSView()
var xLoc: CGFloat = 12
var xLoc2: CGFloat = CGFloat((NSApp.dockTile.contentView?.frame.width ?? 0))
var maxY = (NSApp.dockTile.contentView?.frame.height ?? 0)
var possibleYLocMax: CGFloat = 0.0
func applicationDidFinishLaunching(_ aNotification: Notification) {
// fetch settings
hideScore = UserDefaults.standard.value(forKey: "hideScore") as? Bool ?? false
// create the menu
if let button = statusItem.button {
button.image = NSImage(named: NSImage.Name("smallIcon"))
button.action = #selector(restart(_:))
}
constructMenu()
// set up views and locations
bgView.wantsLayer = true
bgView.layer?.backgroundColor = NSColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 1).cgColor
bgView.layer?.cornerRadius = 25
bgView.layer?.cornerCurve = .continuous
NSApp.dockTile.contentView = bgView
NSApp.dockTile.display()
bgView.frame = CGRect(x: 5, y: 5, width: (NSApp.dockTile.contentView?.frame.width ?? 0) - 12, height: (NSApp.dockTile.contentView?.frame.height ?? 0) - 12)
shipView.wantsLayer = true
shipView.image = NSImage(named: "Triangle")
shipView.layer?.backgroundColor = NSColor.clear.cgColor
shipView.frame = CGRect(x: 12, y: 12, width: 16, height: 16)
bgView.addSubview(shipView)
NSApp.dockTile.display()
xLoc2 = CGFloat((NSApp.dockTile.contentView?.frame.width ?? 0))
self.bgView.addSubview(bullet)
self.bgView.addSubview(enemy)
maxY = (NSApp.dockTile.contentView?.frame.height ?? 0)
possibleYLocMax = Double.random(in: 1...maxY)
// set up global mouse monitoring events
NSEvent.addGlobalMonitorForEvents(matching: NSEvent.EventTypeMask.mouseMoved, handler: {(mouseEvent: NSEvent) in
DispatchQueue.main.async {
let position = mouseEvent.locationInWindow
self.yLoc = CGFloat(position.y)
if self.yLoc > ((NSApp.dockTile.contentView?.frame.height ?? 0) - 24) {
self.shipView.frame.origin.y = ((NSApp.dockTile.contentView?.frame.height ?? 0) - 24)
} else {
self.shipView.frame.origin.y = self.yLoc
}
NSApp.dockTile.display()
}
})
// start timer
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: true)
}
@objc func fireTimer() {
// create bullets and enemies
bullet.wantsLayer = true
if #available(macOS 12.0, *) {
bullet.layer?.backgroundColor = NSColor.systemCyan.cgColor
} else {
bullet.layer?.backgroundColor = NSColor.white.cgColor
}
bullet.layer?.cornerRadius = 3
bullet.frame = CGRect(x: xLoc, y: self.yLoc + 4, width: 6, height: 6)
bullet.frame.origin.x = xLoc
xLoc += 3
if xLoc >= CGFloat((NSApp.dockTile.contentView?.frame.width ?? 0) - 24) {
xLoc = 0
NSApp.dockTile.display()
}
enemy.wantsLayer = true
enemy.layer?.backgroundColor = NSColor.systemPink.cgColor
enemy.layer?.cornerRadius = 5
enemy.frame = CGRect(x: xLoc2, y: possibleYLocMax, width: 10, height: 10)
enemy.frame.origin.x = xLoc2
NSApp.dockTile.display()
xLoc2 -= 0.4
if xLoc2 <= CGFloat(12) {
xLoc2 = CGFloat((NSApp.dockTile.contentView?.frame.width ?? 0))
possibleYLocMax = Double.random(in: 1...maxY)
NSApp.dockTile.display()
}
if (self.bullet.frame.origin.y <= self.enemy.frame.origin.y + 2) && (self.bullet.frame.origin.y >= self.enemy.frame.origin.y - 2) {
self.score += 1
self.xLoc2 = CGFloat((NSApp.dockTile.contentView?.frame.width ?? 0))
self.possibleYLocMax = Double.random(in: 1...self.maxY)
if hideScore {} else {
NSApp.dockTile.badgeLabel = "\(score)"
}
}
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
@objc func restart(_ sender: Any?) {
// reset score
score = 0
NSApp.dockTile.badgeLabel = ""
NSApp.dockTile.display()
}
@objc func toggleBadge(_ sender: Any?) {
// hide or display application badge
hideScore = !hideScore
UserDefaults.standard.set(hideScore, forKey: "hideScore")
if hideScore {
NSApp.dockTile.badgeLabel = ""
} else {
NSApp.dockTile.badgeLabel = "\(score)"
}
constructMenu()
}
func constructMenu() {
// menu options
var bTxt = "Hide Score Badge"
if hideScore {
bTxt = "Show Score Badge"
}
let menu = NSMenu()
let m0 = NSMenuItem(title: "Restart", action: #selector(AppDelegate.restart(_:)), keyEquivalent: "")
menu.addItem(m0)
let m1 = NSMenuItem(title: bTxt, action: #selector(AppDelegate.toggleBadge(_:)), keyEquivalent: "")
menu.addItem(m1)
menu.addItem(NSMenuItem.separator())
menu.addItem(NSMenuItem(title: "Quit Dock Shooter", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q"))
statusItem.menu = menu
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment