the sounds plays but the scene doesn't change, I don't know what to do. I'm a beginner Basically it is a plane shop in my game, but the scene doesn't change. Appreciate any help!
This is my code:
`
extends Control
onready var default_plane_button = $DefaultPlaneButton
onready var plane_1_button = $BuyPlane1
onready var plane_2_button = $BuyPlane2
onready var plane_3_button = $BuyPlane3
onready var plane_4_button = $BuyPlane4
func _on_BuyPlane1_button_up():
var read_dictionary = str2var(change_file().get_as_text())
var new_dictionary = read_dictionary
if new_dictionary["plane_1_bought"] == true:
new_dictionary["plane_equipped"] = 1
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_1_button.text = "Equipped"
elif new_dictionary["coins"] >= 1000:
global.button_click_sound.play()
new_dictionary["coins"] -= 1000
print(new_dictionary)
new_dictionary["plane_1_bought"] = true
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_1_button.text = "Equip"
else:
print("insufficient coins")
global.no_click_sound.play()
func _on_BuyPlane2_button_up():
var read_dictionary = str2var(change_file().get_as_text())
var new_dictionary = read_dictionary
if new_dictionary["plane_2_bought"] == true:
new_dictionary["plane_equipped"] = 2
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_2_button.text = "Equipped"
elif new_dictionary["coins"] >= 2000:
global.button_click_sound.play()
new_dictionary["coins"] -= 2000
new_dictionary["plane_2_bought"] = true
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_2_button.text = "Equip"
else:
print("insufficient coins")
global.no_click_sound.play()
func _on_BuyPlane3_button_up():
var read_dictionary = str2var(change_file().get_as_text())
var new_dictionary = read_dictionary
if new_dictionary["plane_3_bought"] == true:
new_dictionary["plane_equipped"] = 3
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_3_button.text = "Equipped"
elif new_dictionary["coins"] >= 3000:
global.button_click_sound.play()
new_dictionary["coins"] -= 3000
new_dictionary["plane_3_bought"] = true
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_3_button.text = "Equip"
else:
print("insufficient coins")
global.no_click_sound.play()
func _on_BuyPlane4_button_up():
var read_dictionary = str2var(change_file().get_as_text())
var new_dictionary = read_dictionary
if new_dictionary["plane_4_bought"] == true:
new_dictionary["plane_equipped"] = 4
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_4_button.text = "Equipped"
elif new_dictionary["coins"] >= 4269:
global.button_click_sound.play()
new_dictionary["coins"] -= 4269
new_dictionary["plane_4_bought"] = true
change_file().store_string(var2str(new_dictionary))
change_file().close()
plane_4_button.text = "Equip"
else:
print("insufficient coins")
global.no_click_sound.play()
func _on_Back_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/Shop.tscn")
func _on_DefaultPlaneButton_button_up():
global.no_click_sound.play()
var read_dictionary = str2var(change_file().get_as_text())
var new_dictionary = read_dictionary
new_dictionary["plane_equipped"] = 0
change_file().store_string(var2str(new_dictionary))
change_file().close()
change_file().close()
default_plane_button.text = "Equipped"
func change_file():
var file = File.new()
var err = file.open(global.SAVE_FILE, File.READ_WRITE)
if err == OK:
return file
print("open file success")
else:
print("error opening file, error: ", err)
func _on_NextButton_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane2.tscn")
func _on_BackButton_pressed():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane1.tscn")
func _on_NextButton1_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane3.tscn")
func _on_NextButton23_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane.tscn")
func _on_BackButton232_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane.tscn")
func _on_BackButton321312_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane2.tscn")
func _on_NextButton23123_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane4.tscn")
func _on_BackButton2212412_button_up():
global.button_click_sound.play()
get_tree().change_scene("res://Assets/Room/ShopPlane3.tscn")
`
the sounds plays but the scene doesn't change, I don't know what to do. I'm a beginner Basically it is a plane shop in my game, but the scene doesn't change. Appreciate any help!
I edit my answer. Somewhere there i found a way to change scenes that works for me very well. I dont have the reference anymore (if someone does, please tell), but this is the way:
Add a Global.gd script to autoload (Project->Project settings->Autoload) with this code:
extends Node
var current_scene = null
func _ready():
var root = get_tree().root
current_scene = root.get_child(root.get_child_count() - 1)
func goto_scene(path, params=null):
# This function will usually be called from a signal
# callback,
# or some other function in the current scene.
# Deleting the current scene at this point is
# a bad idea, because it may still be executing code.
# This will result in a crash or unexpected behavior.
# The solution is to defer the load to a later time, when
# we can be sure that no code from the current scene is
# running:
call_deferred("_deferred_goto_scene", path)
func _deferred_goto_scene(path):
# It is now safe to remove the current scene
current_scene.free()
# Load the new scene.
var s = ResourceLoader.load(path)
# Instance the new scene.
current_scene = s.instance()
# Add it to the active scene, as child of root.
get_tree().root.add_child(current_scene)
# Optionally, to make it compatible with the
SceneTree.change_scene() API.
get_tree().current_scene = current_scene
Then, when you want to change scene do this:
Global.goto_scene("res://path/yourscene.tscn")?
Related
Hi I am using the function createPoint to animate a polygon using gsap. I am also using svg.js
If I use vanilla javascript to get the points of the svg with
var polygon = document.querySelector("polygon");
var points = polygon.points;
it returns 3 points which correspond to the number of times the createPoint function is run. This logs out as:
0: SVGPoint {x: 105.30396270751953, y: 143.0928955078125}
1: SVGPoint {x: 348.09027099609375, y: 97.7249984741211}
2: SVGPoint {x: 276.54010009765625, y: 327.56372070}
If I use the svg.js code
const draw = SVG().addTo('body')
var svg = draw.node;
const polygon = draw.polygon().node;
var points = polygon.points;
the same function logs a list of 4 SVGPoints with the first point being {x:0,y:0} even though I am only running the function 3 times. Where is the additional (index 0) svg point coming from? Thanks in advance
0: SVGPoint {x: 0, y: 0}
1: SVGPoint {x: 93.79865264892578, y: 124.19292449951172}
2: SVGPoint {x: 346.3572082519531, y: 97.5942153930664}
3: SVGPoint {x: 227.08517456054688, y: 269.97042846
given the following html
<svg>
<polygon points="">
</svg>
And the code below
TweenLite.defaultEase = Sine.easeInOut;
const draw = SVG().addTo('body')
var svg = draw.node;
const polygon = draw.polygon().node;
var points = polygon.points;
console.log('points',points)
var offset = 75;
createPoint(100, 100);
createPoint(300, 100);
createPoint(300, 300);
// createPoint(100, 300);
function createPoint(x, y) {
var minX = x - offset;
var maxX = x + offset;
var minY = y - offset;
var maxY = y + offset;
var point = points.appendItem(svg.createSVGPoint());
point.x = x;
point.y = y;
moveX();
moveY();
function moveX() {
TweenLite.to(point, random(2, 4), {
x: random(minX, maxX),
delay: random(0.5),
onComplete: moveX
});
}
function moveY() {
TweenLite.to(point, random(2, 4), {
y: random(minY, maxY),
delay: random(0.5),
onComplete: moveY
});
}
}
function random(min, max) {
if (max == null) { max = min; min = 0; }
if (min > max) { var tmp = min; min = max; max = tmp; }
return min + (max - min) * Math.random();
}
Just found out that by adding an empty array to the polygon i.e
const polygon = draw.polygon([]).node
it removes the default {x:0,y:0} object. Dont ask me why :)
I'm trying to apply the solution presented in this Question's answer to crop a bitmap using RenderSript. My approach is a little bit different since I'm using bitmap directly as an input to crop.
Having very limited knowledge in RenderScript I developed the below code to crop my bitmap by modifying that answer.
crop.rs
#pragma version(1)
#pragma rs java_package_name(com.xxx.yyy)
#pragma rs_fp_relaxed
int32_t width;
int32_t height;
rs_allocation croppedImg;
uint xStart, yStart;
void __attribute__((kernel)) doCrop(uchar4 in,uint32_t x, uint32_t y) {
rsSetElementAt_uchar4(croppedImg,in, x-xStart, y-yStart);
}
ImageCropper
import android.content.Context
import android.graphics.Bitmap
import androidx.renderscript.*
import com.xxx.yyy.ScriptC_crop
import kotlin.math.abs
class ImageCropper(context: Context?) {
val rs = RenderScript.create(context)
var dx = 0 // (-width < dx < width);
var dy = 250 // (- height < dy < height);
var xStart = 50
var xEnd = 100
var yStart = 50
var yEnd = 100
fun crop(sourceBitmap: Bitmap): Bitmap{
val width = sourceBitmap.width
val height = sourceBitmap.height
if (dx<0) {
xStart = abs(dx)
xEnd= width
} else {
xStart = 0
xEnd = width - abs(dx)
}
if (dy<0) {
yStart= abs(dy)
yEnd=height
} else {
yStart = 0;
yEnd = height - abs(dy)
}
val cropperScript = ScriptC_crop(rs)
val inputType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
val inputAllocation = Allocation.createTyped(rs, inputType, Allocation.USAGE_SCRIPT)
inputAllocation.copyFrom(sourceBitmap)
val outputType = Type.createXY(rs, Element.RGBA_8888(rs), xEnd - xStart, yEnd - yStart)
val outputAllocation = Allocation.createTyped(rs, outputType, Allocation.USAGE_SCRIPT)
cropperScript._croppedImg = outputAllocation
cropperScript._width = width
cropperScript._height = height
cropperScript._xStart = xStart.toLong()
cropperScript._yStart = yStart.toLong()
val launchOptions: Script.LaunchOptions = Script.LaunchOptions()
launchOptions.setX(xStart, xEnd)
launchOptions.setY(yStart, yEnd)
cropperScript.forEach_doCrop(inputAllocation, launchOptions)
val resultBitmap = Bitmap.createBitmap(xEnd - xStart, yEnd - yStart, sourceBitmap.config)
outputAllocation.copyTo(resultBitmap)
rs.destroy()
return resultBitmap
}
}
When I try to execute the code I get a bellow error.
2021-04-11 20:55:41.639 18145-18202/com.chathuranga.shan.renderscriptexample E/RenderScript: Script::setVar unable to set allocation, invalid slot index
2021-04-11 20:55:41.645 18145-18202/com.chathuranga.shan.renderscriptexample A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x519 in tid 18202 (erscriptexample), pid 18145 (erscriptexample)
2021-04-11 20:55:41.639 18145-18202/com.chathuranga.shan.renderscriptexample E/RenderScript: Script::setVar unable to set allocation, invalid slot index
This error occurs in the line where I set _xStart and _yStart values. What am I doing wrong? is it some sort of data type issue?
I am working on image seam carving project, looking for some help. Can someone tell me what am I doing wrong here, Hyperskill is not accepting my solution. I am pretty sure I did not understand the project statement correctly. (I’ve been fighting it for a week)
Project: https://hyperskill.org/projects/100/stages/553/implement
First I am finding the minimum seam from all possible seams.
var minX = 0
// (minSeamX, 0) would be the coordinate of the minimum seam
var minSeamX = 0
var minSeam = Double.MAX_VALUE
//Starting from top left find the sum of pixel energies for all possible seams(#width number of possible seams)
for (column in 0 until width) {
var totalSeam = 0.0
var xHigh = column
var xLow = column
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
if (x < 0 || x > width - 1) continue
val energy = calculateEnergy(x, y, bufferedImage)
// println("Energy $x $y $energy")
if (energy < min) {
min = energy
minX = x
}
}
totalSeam += min
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
if (totalSeam < minSeam) {
minSeamX = column
minSeam = totalSeam
}
println("total:$totalSeam")
}
after that I am applying the color to the minimum seam pixels
var xLow = minSeamX
var xHigh = minSeamX
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
val energy = calculateEnergy(x, y, bufferedImage)
if (energy < min) {
min = energy
minX = x
}
}
val createGraphics = applyColor(outImage, minX, y)
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
Complete code
package seamcarving
import java.awt.Color
import java.awt.Graphics2D
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import kotlin.math.pow
import kotlin.math.sqrt
fun main(args: Array<String>) {
val bufferedImage = ImageIO.read(File("/Users/name/Downloads/images/blue.png"))
val outImage = ImageIO.read(File("/Users/name/Downloads/images/blue.png"))
val height = bufferedImage.height
val width = bufferedImage.width
var minX = 0
// (minSeamX, 0) would be the coordinate of the minimum seam
var minSeamX = 0
var minSeam = Double.MAX_VALUE
//Starting from top left find the sum of pixel energies for all possible seams(#width number of possible seams)
for (column in 0 until width) {
var totalSeam = 0.0
var xHigh = column
var xLow = column
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
if (x < 0 || x > width - 1) continue
val energy = calculateEnergy(x, y, bufferedImage)
// println("Energy $x $y $energy")
if (energy < min) {
min = energy
minX = x
}
}
totalSeam += min
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
if (totalSeam < minSeam) {
minSeamX = column
minSeam = totalSeam
}
println("total:$totalSeam")
}
var xLow = minSeamX
var xHigh = minSeamX
var min = Double.MAX_VALUE
for (y in 0 until height) {
for (x in xLow..xHigh) {
val energy = calculateEnergy(x, y, bufferedImage)
if (energy < min) {
min = energy
minX = x
}
}
val createGraphics = applyColor(outImage, minX, y)
min = Double.MAX_VALUE
xLow = minX - 1
xHigh = minX + 1
}
// for (x in 0 until width) {
// for (y in 0 until height) {
// val intensity = ((255.0 * array[x][y]) / max).toInt()
// val color = Color(intensity, intensity, intensity)
//// outputImage.setRGB(x, y, intensity)
// createGraphics.paint = color
// createGraphics.fillRect(x, y, 1, 1)
// }
// }
ImageIO.write(outImage, "png", File("out.png"))
// ImageIO.write(bufferedImage, "png", File("${args[3]}"))
}
private fun applyColor(outputImage: BufferedImage, maxX: Int, maxY: Int): Graphics2D? {
val createGraphics = outputImage.createGraphics()
val color = Color(255, 0, 0)
createGraphics.paint = color
createGraphics.fillRect(maxX, maxY, 1, 1)
return createGraphics
}
private fun calculateEnergy(x: Int, y: Int, bufferedImage: BufferedImage): Double {
return sqrt(getXGradient(x, y, bufferedImage) + getYGradient(x, y, bufferedImage))
}
fun getXGradient(x: Int, y: Int, inImage: BufferedImage): Double {
val width = inImage.width
var xx = x
var yy = y
if (x == 0) xx = 1
if (x == width - 1) xx = x - 1
val lc = Color(inImage.getRGB(xx - 1, yy))
val rc = Color(inImage.getRGB(xx + 1, yy))
return (lc.red - rc.red).toDouble().pow(2.0) + (lc.green - rc.green).toDouble().pow(2.0) + (lc.blue - rc.blue).toDouble().pow(2.0)
}
fun getYGradient(x: Int, y: Int, inImage: BufferedImage): Double {
val height = inImage.height
var xx = x
var yy = y
if (y == 0) yy = 1
if (y == height - 1) yy = y - 1
val lc = Color(inImage.getRGB(xx, yy - 1))
val rc = Color(inImage.getRGB(xx, yy + 1))
return (lc.red - rc.red).toDouble().pow(2.0) + (lc.green - rc.green).toDouble().pow(2.0) + (lc.blue - rc.blue).toDouble().pow(2.0)
}
Got this Arkanoid clone code from internet however even after installing pygame binary still doesn' t want to work ("ImportError: No module named 'Models'"). I am using Spyder Python 3.5 and i cloned all repo from there https://github.com/Killavus/PyGame-Arkanoid
import pygame
import sys
import math
import random
from pygame.locals import *
import GameModule
from GameModule.Models import *
from GameModule.Constants import *
class Game:
def playSound( self, fileName ):
sound = pygame.mixer.Sound(fileName)
sound.play()
def __init__(self):
pygame.init()
pygame.mixer.init(11025)
self.actualState = states["START"]
self.display = pygame.display.set_mode( gfx["screen"] )
pygame.display.set_caption( "Arkanoid v" + version )
# 4 basic objects, which define the game
## Painter - drawing actual situation on screen
## Mapper - loading the map
## Status - holding stance of the game: points, lifes, actual powerups etc
## Objects - holding actual game's objects: balls, bricks, pad etc
self.objects = GameModule.Objects()
self.mapper = GameModule.Mapper( self.objects )
self.status = Status()
self.painter = GameModule.Painter( self.display, self.objects, self.status )
self.lastState = None
self.fps = pygame.time.Clock()
self.newLevel()
def loop(self):
self.fps.tick( gfx["framerate"] )
for event in pygame.event.get():
self.handleGlobalEvents( event )
self.handleEvents( event )
self.handleKeyboard()
self.updateState()
if self.actualState != states["GAMEOVER"]:
self.painter.draw()
else:
self.display.fill( (0,0,0) )
bigFont = pygame.font.SysFont( "sans-serif", 32 )
gameOver = bigFont.render( "GAME OVER!", True, (255,255,255) )
smallFont = pygame.font.SysFont( "sans-serif", 18 )
points = smallFont.render( "Punktow: " + str(self.status.points), True, (255,255,255) )
self.display.blit( gameOver, (gfx["screen"][0]/2 - gameOver.get_size()[0]/2, gfx["screen"][1]/2 - gameOver.get_size()[1]/2) )
self.display.blit( points, (gfx["screen"][0]/2 - points.get_size()[0]/2, gfx["screen"][1]/2 - gameOver.get_size()[1]/2 - 40) )
pygame.display.update()
def handleEvents( self, event ):
if self.actualState != states["PAUSE"]:
if event.type == KEYDOWN:
if event.key == K_p:
self.lastState = self.actualState
self.actualState = states["PAUSE"]
self.painter.paused = True
else:
if event.type == KEYDOWN:
if event.key == K_p:
self.actualState = self.lastState
self.painter.paused = False
if self.actualState == states["START"]:
if event.type == KEYDOWN:
if event.key == K_SPACE:
self.actualState = states["PROGRESS"]
(self.objects.balls())[0].speedChange( int( math.copysign( 5., float(self.objects.pad().lastMove) ) ), -5 )
def handleGlobalEvents( self, event ):
if event.type == QUIT:
sys.exit()
def handleKeyboard(self):
pressed = pygame.key.get_pressed()
if self.actualState == states["PROGRESS"] or self.actualState == states["START"]:
if pressed[K_LEFT]:
if self.objects.pad().move(-10) and self.actualState == states["START"]:
(self.objects.balls())[0].move(-10,0)
if pressed[K_RIGHT]:
if self.objects.pad().move(10) and self.actualState == states["START"]:
(self.objects.balls())[0].move(10,0)
def updateState(self):
if self.actualState == states["PAUSE"]:
return
if self.actualState == states["PROGRESS"]:
self.objects.updatePowerups()
for ball in self.objects.balls():
speed = ball.speed()
ball.move( speed[0], speed[1] )
if ball.collideWithWall():
pos = ball.pos()
if pos[0] == 0 or pos[0] >= gfx["screen"][0] - ball.image.get_size()[0] - 1:
ball.xInvert()
if pos[1] == 0:
ball.yInvert()
if pos[1] >= gfx["screen"][1] - ball.image.get_size()[1] - 1:
self.status.lives -= 1
self.actualState = states["START"]
self.playSound( "Resources/snd/chord.wav" )
while len(self.objects.balls()) != 1:
self.objects.removeBall((self.objects.balls())[0])
for powerup in self.objects.powerups():
self.objects.deletePowerup(powerup)
self.objects.balls()[0].reset()
self.objects.pad().reset()
for obj in self.objects.grid():
if ball.collision(obj):
self.status.points += 100
if obj.realx <= ball.position[0] and obj.realx + gfx["grid"][0] >= ball.position[0]:
ball.yInvert()
if obj.realy <= ball.position[1] and obj.realy + gfx["grid"][1] >= ball.position[1]:
ball.xInvert()
self.handleBrickCollision(obj)
if ball.collision(self.objects.pad()):
ball.yInvert()
if self.objects.pad().position[1] <= ball.position[1] and self.objects.pad().position[1] + gfx["grid"][1] >= ball.position[1]:
ball.xInvert()
for powerup in self.objects.powerups():
pad = self.objects.pad()
if powerup.collision(pad):
self.objects.deletePowerup(powerup)
self.generatePowerup()
if powerup.y == gfx["screen"][1] - 1 - powerup.image.get_size()[1]:
self.objects.deletePowerup(powerup)
if self.status.lives == 0:
self.actualState = states["GAMEOVER"]
if self.objects.grid() == []:
self.status.level += 1
if len(levels) == self.status.level:
self.actualStatus = states["GAMEOVER"]
else:
self.newLevel()
for modifier in self.status.modifiers:
modifier[1] -= 1
if modifier[1] == 0:
if modifier[0] == "big_pad":
self.objects.pad().setWidth(3)
del modifier
def generatePowerup(self):
r = random.randint(1,3)
# 3 possible powerups:
# 1 - +1 life
# 2 - for 30 sec the pad is larger
# 3 - additional ball
print (r)
if r == 1:
self.status.lives += 1
elif r == 2:
self.status.modifiers.append( [ "big_pad", gfx["framerate"] * 30 ] )
self.objects.pad().setWidth(5)
elif r == 3:
ball = Ball()
ball.position[0] = self.objects.pad().position[0] + (gfx["grid"][0]*self.objects.pad().gridWidth/2)
ball.speedChange( int( math.copysign( 5., float(self.objects.pad().lastMove) ) ), -5 )
self.objects.addBall(ball)
def handleBrickCollision(self,obj):
brickType = obj.getType()
if brickType == "simple":
self.objects.setGrid( obj.x, obj.y, None )
rand = random.randint( 0, 9 )
if rand == 9: # 1/10 chance for powerup
self.objects.spawnPowerup( obj.x, obj.y )
elif brickType == "solid":
self.objects.setGrid( obj.x, obj.y, SimpleBrick(obj.x,obj.y) )
elif brickType == "ghost":
newType = random.randint( 0, 1 )
if newType == 0:
self.objects.setGrid( obj.x, obj.y, SimpleBrick(obj.x,obj.y) )
elif newType == 1:
self.objects.setGrid( obj.x, obj.y, SolidBrick(obj.x,obj.y) )
self.playSound( "Resources/snd/ding.wav" )
def newLevel(self):
self.playSound( "Resources/snd/tada.wav" )
self.mapper.load( self.status.level )
self.objects.pad().reset()
while len(self.objects.balls()) != 1:
self.objects.removeBall((self.objects.balls())[0])
self.objects.balls()[0].reset()
self.actualState = states["START"]
class Status:
def __init__(self):
self.level = 0
self.points = 0
self.lives = startState["lives"]
self.modifiers = []
game = Game()
while True:
game.loop()
Translating Obj-C to Swift. As you can see I declared let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef)) so I'm getting the error in the for loop below it.
Binary operator '+=' cannot be applied to operands of type 'Int' and 'UInt8'
Also as a little addendum I don't know how to translate the remaining Obj-C code below the for loop. What does that slash mean and how do I deal with the pointer? I have to say UnsafeMutableFloat somewhere?
// process the frame of video
func captureOutput(captureOutput:AVCaptureOutput, didOutputSampleBuffer sampleBuffer:CMSampleBuffer, fromConnection connection:AVCaptureConnection) {
// if we're paused don't do anything
if currentState == CurrentState.statePaused {
// reset our frame counter
self.validFrameCounter = 0
return
}
// this is the image buffer
var cvimgRef:CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)
// Lock the image buffer
CVPixelBufferLockBaseAddress(cvimgRef, 0)
// access the data
var width: size_t = CVPixelBufferGetWidth(cvimgRef)
var height:size_t = CVPixelBufferGetHeight(cvimgRef)
// get the raw image bytes
let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef))
var bprow: size_t = CVPixelBufferGetBytesPerRow(cvimgRef)
var r = 0
var g = 0
var b = 0
for var y = 0; y < height; y++ {
for var x = 0; x < width * 4; x += 4 {
b += buf[x]; g += buf[x + 1]; r += buf[x + 2] // error
}
buf += bprow() // error
}
Remaining Obj-C code.
r/=255*(float) (width*height);
g/=255*(float) (width*height);
b/=255*(float) (width*height);
You have a lot of type mismatch error.
The type of x should not be UInt8 because x to increase until the value of the width.
for var x:UInt8 = 0; x < width * 4; x += 4 { // error: '<' cannot be applied to operands of type 'UInt8' and 'Int'
So fix it like below:
for var x = 0; x < width * 4; x += 4 {
To increment the pointer address, you can use advancedBy() function.
buf += bprow(UnsafeMutablePointer(UInt8)) // error: '+=' cannot be applied to operands of type 'UnsafeMutablePointer<UInt8>' and 'size_t'
Like below:
var pixel = buf.advancedBy(y * bprow)
And this line,
RGBtoHSV(r, g, b) // error
There are no implicit casts in Swift between CGFloat and Float unfortunately. So you should cast explicitly to CGFloat.
RGBtoHSV(CGFloat(r), g: CGFloat(g), b: CGFloat(b))
The whole edited code is here:
func RGBtoHSV(r: CGFloat, g: CGFloat, b: CGFloat) -> (h: CGFloat, s: CGFloat, v: CGFloat) {
var h: CGFloat = 0.0
var s: CGFloat = 0.0
var v: CGFloat = 0.0
let col = UIColor(red: r, green: g, blue: b, alpha: 1.0)
col.getHue(&h, saturation: &s, brightness: &v, alpha: nil)
return (h, s, v)
}
// process the frame of video
func captureOutput(captureOutput:AVCaptureOutput, didOutputSampleBuffer sampleBuffer:CMSampleBuffer, fromConnection connection:AVCaptureConnection) {
// if we're paused don't do anything
if currentState == CurrentState.statePaused {
// reset our frame counter
self.validFrameCounter = 0
return
}
// this is the image buffer
var cvimgRef = CMSampleBufferGetImageBuffer(sampleBuffer)
// Lock the image buffer
CVPixelBufferLockBaseAddress(cvimgRef, 0)
// access the data
var width = CVPixelBufferGetWidth(cvimgRef)
var height = CVPixelBufferGetHeight(cvimgRef)
// get the raw image bytes
let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(cvimgRef))
var bprow = CVPixelBufferGetBytesPerRow(cvimgRef)
var r: Float = 0.0
var g: Float = 0.0
var b: Float = 0.0
for var y = 0; y < height; y++ {
var pixel = buf.advancedBy(y * bprow)
for var x = 0; x < width * 4; x += 4 { // error: '<' cannot be applied to operands of type 'UInt8' and 'Int'
b += Float(pixel[x])
g += Float(pixel[x + 1])
r += Float(pixel[x + 2])
}
}
r /= 255 * Float(width * height)
g /= 255 * Float(width * height)
b /= 255 * Float(width * height)
//}
// convert from rgb to hsv colourspace
var h: Float = 0.0
var s: Float = 0.0
var v: Float = 0.0
RGBtoHSV(CGFloat(r), g: CGFloat(g), b: CGFloat(b)) // error
}