Created
November 3, 2021 09:53
-
-
Save ShihabM/b75321e7f497f17ff3d9d65afd5557d6 to your computer and use it in GitHub Desktop.
Dock Shooter - a game in your dock icon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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